Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2012 Intel Corporation.  All rights reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  */
     17 #include <cutils/properties.h>
     18 #include <system/graphics.h>
     19 #include "isv_worker.h"
     20 #ifndef TARGET_VPP_USE_GEN
     21 #include <hal_public.h>
     22 #else
     23 #include <ufo/graphics.h>
     24 #endif
     25 
     26 //#define LOG_NDEBUG 0
     27 #undef LOG_TAG
     28 #define LOG_TAG "isv-omxil"
     29 
     30 #define CHECK_VASTATUS(str) \
     31     do { \
     32         if (vaStatus != VA_STATUS_SUCCESS) { \
     33                 ALOGE("%s failed\n", str); \
     34                 return STATUS_ERROR;}   \
     35         }while(0);
     36 
     37 enum STRENGTH {
     38     STRENGTH_LOW = 0,
     39     STRENGTH_MEDIUM,
     40     STRENGTH_HIGH
     41 };
     42 
     43 #define DENOISE_DEBLOCK_STRENGTH STRENGTH_MEDIUM
     44 #define COLOR_STRENGTH STRENGTH_MEDIUM
     45 #ifdef TARGET_VPP_USE_GEN
     46 #define COLOR_NUM 4
     47 #else
     48 #define COLOR_NUM 2
     49 #endif
     50 
     51 #define MAX_FRC_OUTPUT 4 /*for frcx4*/
     52 
     53 using namespace android;
     54 
     55 ISVWorker::ISVWorker()
     56     :mNumForwardReferences(0),
     57     mVAContext(VA_INVALID_ID),
     58     mWidth(0), mHeight(0),
     59     mDisplay(NULL), mVADisplay(NULL),
     60     mVAConfig(VA_INVALID_ID),
     61     mForwardReferences(NULL),
     62     mPrevInput(0), mPrevOutput(0),
     63     mNumFilterBuffers(0),
     64     mFilterFrc(VA_INVALID_ID), mFilters(0),
     65     mInputIndex(0), mOutputIndex(0),
     66     mOutputCount(0) {
     67     memset(&mFilterBuffers, VA_INVALID_ID, VAProcFilterCount * sizeof(VABufferID));
     68     memset(&mFilterParam, 0, sizeof(mFilterParam));
     69 }
     70 
     71 bool ISVWorker::isSupport() const {
     72     bool support = false;
     73 
     74     int num_entrypoints = vaMaxNumEntrypoints(mVADisplay);
     75     VAEntrypoint * entrypoints = (VAEntrypoint *)malloc(num_entrypoints * sizeof(VAEntrypoint));
     76     if (entrypoints == NULL) {
     77         ALOGE("failed to malloc entrypoints array\n");
     78         return false;
     79     }
     80 
     81     // check if it contains VPP entry point VAEntrypointVideoProc
     82     VAStatus vaStatus = vaQueryConfigEntrypoints(mVADisplay, VAProfileNone, entrypoints, &num_entrypoints);
     83     if (vaStatus != VA_STATUS_SUCCESS) {
     84         ALOGE("vaQueryConfigEntrypoints failed");
     85         return false;
     86     }
     87     for (int i = 0; !support && i < num_entrypoints; i++) {
     88         support = entrypoints[i] == VAEntrypointVideoProc;
     89     }
     90     free(entrypoints);
     91     entrypoints = NULL;
     92 
     93     return support;
     94 }
     95 
     96 uint32_t ISVWorker::getProcBufCount() {
     97     return getOutputBufCount(mInputIndex);
     98 }
     99 
    100 uint32_t ISVWorker::getFillBufCount() {
    101         return getOutputBufCount(mOutputIndex);
    102 }
    103 
    104 uint32_t ISVWorker::getOutputBufCount(uint32_t index) {
    105     uint32_t bufCount = 1;
    106     if (((mFilters & FilterFrameRateConversion) != 0)
    107             && index > 0)
    108             bufCount = mFilterParam.frcRate - (((mFilterParam.frcRate == FRC_RATE_2_5X) ? (index & 1): 0));
    109     return bufCount;
    110 }
    111 
    112 
    113 status_t ISVWorker::init(uint32_t width, uint32_t height) {
    114     ALOGV("init");
    115 
    116     if (mDisplay != NULL) {
    117         ALOGE("VA is particially started");
    118         return STATUS_ERROR;
    119     }
    120     mDisplay = new Display;
    121     *mDisplay = ANDROID_DISPLAY_HANDLE;
    122 
    123     mVADisplay = vaGetDisplay(mDisplay);
    124     if (mVADisplay == NULL) {
    125         ALOGE("vaGetDisplay failed");
    126         return STATUS_ERROR;
    127     }
    128 
    129     int majorVersion, minorVersion;
    130     VAStatus vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion);
    131     CHECK_VASTATUS("vaInitialize");
    132 
    133     // Check if VPP entry point is supported
    134     if (!isSupport()) {
    135         ALOGE("VPP is not supported on current platform");
    136         return STATUS_NOT_SUPPORT;
    137     }
    138 
    139     // Find out the format for the target
    140     VAConfigAttrib attrib;
    141     attrib.type = VAConfigAttribRTFormat;
    142     vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileNone, VAEntrypointVideoProc, &attrib, 1);
    143     CHECK_VASTATUS("vaGetConfigAttributes");
    144 
    145     if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) {
    146         ALOGE("attribute is %x vs wanted %x", attrib.value, VA_RT_FORMAT_YUV420);
    147         return STATUS_NOT_SUPPORT;
    148     }
    149 
    150     ALOGV("ready to create config");
    151     // Create the configuration
    152     vaStatus = vaCreateConfig(mVADisplay, VAProfileNone, VAEntrypointVideoProc, &attrib, 1, &mVAConfig);
    153     CHECK_VASTATUS("vaCreateConfig");
    154 
    155 
    156     // Create Context
    157     ALOGV("ready to create context");
    158     mWidth = width;
    159     mHeight = height;
    160     vaStatus = vaCreateContext(mVADisplay, mVAConfig, mWidth, mHeight, 0, NULL, 0, &mVAContext);
    161     CHECK_VASTATUS("vaCreateContext");
    162 
    163     ALOGV("VA has been successfully started");
    164     return STATUS_OK;
    165 }
    166 
    167 status_t ISVWorker::deinit() {
    168     {
    169         Mutex::Autolock autoLock(mPipelineBufferLock);
    170         while (!mPipelineBuffers.isEmpty()) {
    171             VABufferID pipelineBuffer = mPipelineBuffers.itemAt(0);
    172             if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, pipelineBuffer))
    173                 ALOGW("%s: failed to destroy va buffer id %d", __func__, pipelineBuffer);
    174             mPipelineBuffers.removeAt(0);
    175         }
    176     }
    177 
    178     if (mNumFilterBuffers != 0) {
    179         for (uint32_t i = 0; i < mNumFilterBuffers; i++) {
    180             if(VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, mFilterBuffers[i]))
    181                 ALOGW("%s: failed to destroy va buffer id %d", __func__, mFilterBuffers[i]);
    182         }
    183         mNumFilterBuffers = 0;
    184         memset(&mFilterBuffers, VA_INVALID_ID, VAProcFilterCount * sizeof(VABufferID));
    185         mFilterFrc = VA_INVALID_ID;
    186     }
    187 
    188     if (mForwardReferences != NULL) {
    189         free(mForwardReferences);
    190         mForwardReferences = NULL;
    191         mNumForwardReferences = 0;
    192     }
    193 
    194     if (mVAContext != VA_INVALID_ID) {
    195          vaDestroyContext(mVADisplay, mVAContext);
    196          mVAContext = VA_INVALID_ID;
    197     }
    198 
    199     if (mVAConfig != VA_INVALID_ID) {
    200         vaDestroyConfig(mVADisplay, mVAConfig);
    201         mVAConfig = VA_INVALID_ID;
    202     }
    203 
    204     if (mVADisplay) {
    205         vaTerminate(mVADisplay);
    206         mVADisplay = NULL;
    207     }
    208 
    209     if (mDisplay) {
    210         delete mDisplay;
    211         mDisplay = NULL;
    212     }
    213 
    214     return STATUS_OK;
    215 }
    216 
    217 status_t ISVWorker::allocSurface(uint32_t* width, uint32_t* height,
    218         uint32_t stride, uint32_t format, unsigned long handle, int32_t* surfaceId)
    219 {
    220     if (mWidth == 0 || mHeight == 0) {
    221         ALOGE("%s: isv worker has not been initialized.", __func__);
    222         return STATUS_ERROR;
    223     }
    224 
    225 #ifndef TARGET_VPP_USE_GEN
    226     *width = mWidth;
    227     *height = mHeight;
    228 #endif
    229     // Create VASurfaces
    230     VASurfaceAttrib attribs[3];
    231     VASurfaceAttribExternalBuffers vaExtBuf;
    232 
    233     memset(&vaExtBuf, 0, sizeof(VASurfaceAttribExternalBuffers));
    234     switch(format) {
    235         case HAL_PIXEL_FORMAT_YV12:
    236             vaExtBuf.pixel_format = VA_FOURCC_YV12;
    237             vaExtBuf.num_planes = 3;
    238             vaExtBuf.pitches[0] = stride;
    239             vaExtBuf.pitches[1] = stride / 2;
    240             vaExtBuf.pitches[2] = stride / 2;
    241             vaExtBuf.pitches[3] = 0;
    242             vaExtBuf.offsets[0] = 0;
    243             vaExtBuf.offsets[1] = stride * *height;
    244             vaExtBuf.offsets[2] = vaExtBuf.offsets[1] + (stride / 2) * (*height / 2);
    245             vaExtBuf.offsets[3] = 0;
    246             break;
    247 #ifdef TARGET_VPP_USE_GEN
    248         case HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL:
    249         case HAL_PIXEL_FORMAT_NV12_X_TILED_INTEL:
    250         //it will be removed in future, it indicate the same format with HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL
    251         case HAL_PIXEL_FORMAT_YUV420PackedSemiPlanar_Tiled_INTEL:
    252 #else
    253         case HAL_PIXEL_FORMAT_NV12_VED:
    254         case HAL_PIXEL_FORMAT_NV12_VEDT:
    255 #endif
    256             vaExtBuf.pixel_format = VA_FOURCC_NV12;
    257             vaExtBuf.num_planes = 2;
    258             vaExtBuf.pitches[0] = stride;
    259             vaExtBuf.pitches[1] = stride;
    260             vaExtBuf.pitches[2] = 0;
    261             vaExtBuf.pitches[3] = 0;
    262             vaExtBuf.offsets[0] = 0;
    263             vaExtBuf.offsets[1] = stride * *height;
    264             vaExtBuf.offsets[2] = 0;
    265             vaExtBuf.offsets[3] = 0;
    266             break;
    267         default:
    268             ALOGE("%s: can't support this format 0x%08x", __func__, format);
    269             return STATUS_ERROR;
    270     }
    271     vaExtBuf.width = *width;
    272     vaExtBuf.height = *height;
    273     vaExtBuf.data_size = stride * *height * 1.5;
    274     vaExtBuf.num_buffers = 1;
    275 #ifndef TARGET_VPP_USE_GEN
    276     if (format == HAL_PIXEL_FORMAT_NV12_VEDT) {
    277         ALOGV("set TILING flag");
    278         vaExtBuf.flags |= VA_SURFACE_EXTBUF_DESC_ENABLE_TILING;
    279     }
    280 #endif
    281     vaExtBuf.flags |= VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
    282     vaExtBuf.buffers = (long unsigned int*)&handle;
    283 
    284     attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
    285     attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
    286     attribs[0].value.type = VAGenericValueTypeInteger;
    287     attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
    288 
    289     attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
    290     attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
    291     attribs[1].value.type = VAGenericValueTypePointer;
    292     attribs[1].value.value.p = &vaExtBuf;
    293 
    294     attribs[2].type = (VASurfaceAttribType)VASurfaceAttribUsageHint;
    295     attribs[2].flags = VA_SURFACE_ATTRIB_SETTABLE;
    296     attribs[2].value.type = VAGenericValueTypeInteger;
    297     attribs[2].value.value.i = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_READ;
    298 
    299     ALOGV("%s: Ext buffer: width %d, height %d, data_size %d, pitch %d", __func__,
    300             vaExtBuf.width, vaExtBuf.height, vaExtBuf.data_size, vaExtBuf.pitches[0]);
    301     VAStatus vaStatus = vaCreateSurfaces(mVADisplay, VA_RT_FORMAT_YUV420, vaExtBuf.width,
    302                                  vaExtBuf.height, (VASurfaceID*)surfaceId, 1, attribs, 3);
    303     CHECK_VASTATUS("vaCreateSurfaces");
    304 
    305     return (vaStatus == VA_STATUS_SUCCESS) ? STATUS_OK : STATUS_ERROR;
    306 }
    307 
    308 status_t ISVWorker::freeSurface(int32_t* surfaceId)
    309 {
    310     VAStatus vaStatus = VA_STATUS_SUCCESS;
    311     vaDestroySurfaces(mVADisplay, (VASurfaceID*)surfaceId, 1);
    312     CHECK_VASTATUS("vaDestroySurfaces");
    313 
    314     return (vaStatus == VA_STATUS_SUCCESS) ? STATUS_OK : STATUS_ERROR;
    315 }
    316 
    317 status_t ISVWorker::configFilters(uint32_t filters,
    318                                   const FilterParam* filterParam)
    319 {
    320     status_t ret = STATUS_OK;
    321 
    322     if (!filterParam) {
    323         ALOGE("%s: invalid filterParam", __func__);
    324         return STATUS_ERROR;
    325     }
    326 
    327     if (filters != 0) {
    328         mFilterParam.srcWidth = filterParam->srcWidth;
    329         mFilterParam.srcHeight = filterParam->srcHeight;
    330         mFilterParam.dstWidth = filterParam->dstWidth;
    331         mFilterParam.dstHeight = filterParam->dstHeight;
    332         mFilterParam.frameRate = filterParam->frameRate;
    333         mFilterParam.frcRate = filterParam->frcRate;
    334     }
    335 
    336     if (mFilters != filters) {
    337         mFilters = filters;
    338         ALOGI("%s: mFilters 0x%x, fps %d, frc rate %d", __func__, mFilters, mFilterParam.frameRate, mFilterParam.frcRate);
    339         ret = setupFilters();
    340     }
    341 
    342     return ret;
    343 }
    344 
    345 bool ISVWorker::isFpsSupport(int32_t fps, int32_t *fpsSet, int32_t fpsSetCnt) {
    346     bool ret = false;
    347     for (int32_t i = 0; i < fpsSetCnt; i++) {
    348         if (fps == fpsSet[i]) {
    349             ret = true;
    350             break;
    351         }
    352     }
    353 
    354     return ret;
    355 }
    356 
    357 status_t ISVWorker::setupFilters() {
    358     ALOGV("setupFilters");
    359     VAProcFilterParameterBuffer deblock, denoise, sharpen, stde;
    360     VAProcFilterParameterBufferDeinterlacing deint;
    361     VAProcFilterParameterBufferColorBalance color[COLOR_NUM];
    362     VAProcFilterParameterBufferFrameRateConversion frc;
    363     VABufferID deblockId, denoiseId, deintId, sharpenId, colorId, frcId, stdeId;
    364     uint32_t numCaps;
    365     VAProcFilterCap deblockCaps, denoiseCaps, sharpenCaps, frcCaps, stdeCaps;
    366     VAProcFilterCapDeinterlacing deinterlacingCaps[VAProcDeinterlacingCount];
    367     VAProcFilterCapColorBalance colorCaps[COLOR_NUM];
    368     VAStatus vaStatus;
    369     uint32_t numSupportedFilters = VAProcFilterCount;
    370     VAProcFilterType supportedFilters[VAProcFilterCount];
    371 
    372     if (mNumFilterBuffers != 0) {
    373         for (uint32_t i = 0; i < mNumFilterBuffers; i++) {
    374             if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, mFilterBuffers[i]))
    375                 ALOGW("%s: failed to destroy va buffer %d", __func__, mFilterBuffers[i]);
    376                 //return STATUS_ERROR;
    377         }
    378         memset(&mFilterBuffers, VA_INVALID_ID, VAProcFilterCount * sizeof(VABufferID));
    379         mFilterFrc = VA_INVALID_ID;
    380         mNumFilterBuffers = 0;
    381     }
    382 
    383     // query supported filters
    384     vaStatus = vaQueryVideoProcFilters(mVADisplay, mVAContext, supportedFilters, &numSupportedFilters);
    385     CHECK_VASTATUS("vaQueryVideoProcFilters");
    386 
    387     // create filter buffer for each filter
    388     for (uint32_t i = 0; i < numSupportedFilters; i++) {
    389         switch (supportedFilters[i]) {
    390             case VAProcFilterDeblocking:
    391                 if ((mFilters & FilterDeblocking) != 0) {
    392                     // check filter caps
    393                     numCaps = 1;
    394                     vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
    395                             VAProcFilterDeblocking,
    396                             &deblockCaps,
    397                             &numCaps);
    398                     CHECK_VASTATUS("vaQueryVideoProcFilterCaps for deblocking");
    399                     // create parameter buffer
    400                     deblock.type = VAProcFilterDeblocking;
    401                     deblock.value = deblockCaps.range.min_value + DENOISE_DEBLOCK_STRENGTH * deblockCaps.range.step;
    402                     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    403                         VAProcFilterParameterBufferType, sizeof(deblock), 1,
    404                         &deblock, &deblockId);
    405                     CHECK_VASTATUS("vaCreateBuffer for deblocking");
    406                     mFilterBuffers[mNumFilterBuffers] = deblockId;
    407                     mNumFilterBuffers++;
    408                 }
    409                 break;
    410             case VAProcFilterNoiseReduction:
    411                 if((mFilters & FilterNoiseReduction) != 0) {
    412                     // check filter caps
    413                     numCaps = 1;
    414                     vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
    415                             VAProcFilterNoiseReduction,
    416                             &denoiseCaps,
    417                             &numCaps);
    418                     CHECK_VASTATUS("vaQueryVideoProcFilterCaps for denoising");
    419                     // create parameter buffer
    420                     denoise.type = VAProcFilterNoiseReduction;
    421 #ifdef TARGET_VPP_USE_GEN
    422                     char propValueString[PROPERTY_VALUE_MAX];
    423 
    424                     // placeholder for vpg driver: can't support denoise factor auto adjust, so leave config to user.
    425                     property_get("vpp.filter.denoise.factor", propValueString, "64.0");
    426                     denoise.value = atof(propValueString);
    427                     denoise.value = (denoise.value < 0.0f) ? 0.0f : denoise.value;
    428                     denoise.value = (denoise.value > 64.0f) ? 64.0f : denoise.value;
    429 #else
    430                     denoise.value = denoiseCaps.range.min_value + DENOISE_DEBLOCK_STRENGTH * denoiseCaps.range.step;
    431 #endif
    432                     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    433                         VAProcFilterParameterBufferType, sizeof(denoise), 1,
    434                         &denoise, &denoiseId);
    435                     CHECK_VASTATUS("vaCreateBuffer for denoising");
    436                     mFilterBuffers[mNumFilterBuffers] = denoiseId;
    437                     mNumFilterBuffers++;
    438                 }
    439                 break;
    440             case VAProcFilterDeinterlacing:
    441                 if ((mFilters & FilterDeinterlacing) != 0) {
    442                     numCaps = VAProcDeinterlacingCount;
    443                     vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
    444                             VAProcFilterDeinterlacing,
    445                             &deinterlacingCaps[0],
    446                             &numCaps);
    447                     CHECK_VASTATUS("vaQueryVideoProcFilterCaps for deinterlacing");
    448                     for (uint32_t i = 0; i < numCaps; i++)
    449                     {
    450                         VAProcFilterCapDeinterlacing * const cap = &deinterlacingCaps[i];
    451                         if (cap->type != VAProcDeinterlacingBob) // desired Deinterlacing Type
    452                             continue;
    453 
    454                         deint.type = VAProcFilterDeinterlacing;
    455                         deint.algorithm = VAProcDeinterlacingBob;
    456                         vaStatus = vaCreateBuffer(mVADisplay,
    457                                 mVAContext,
    458                                 VAProcFilterParameterBufferType,
    459                                 sizeof(deint), 1,
    460                                 &deint, &deintId);
    461                         CHECK_VASTATUS("vaCreateBuffer for deinterlacing");
    462                         mFilterBuffers[mNumFilterBuffers] = deintId;
    463                         mNumFilterBuffers++;
    464                     }
    465                 }
    466                 break;
    467             case VAProcFilterSharpening:
    468                 if((mFilters & FilterSharpening) != 0) {
    469                     // check filter caps
    470                     numCaps = 1;
    471                     vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
    472                             VAProcFilterSharpening,
    473                             &sharpenCaps,
    474                             &numCaps);
    475                     CHECK_VASTATUS("vaQueryVideoProcFilterCaps for sharpening");
    476                     // create parameter buffer
    477                     sharpen.type = VAProcFilterSharpening;
    478 #ifdef TARGET_VPP_USE_GEN
    479                     char propValueString[PROPERTY_VALUE_MAX];
    480 
    481                     // placeholder for vpg driver: can't support sharpness factor auto adjust, so leave config to user.
    482                     property_get("vpp.filter.sharpen.factor", propValueString, "8.0");
    483                     sharpen.value = atof(propValueString);
    484                     sharpen.value = (sharpen.value < 0.0f) ? 0.0f : sharpen.value;
    485                     sharpen.value = (sharpen.value > 64.0f) ? 64.0f : sharpen.value;
    486 #else
    487                     sharpen.value = sharpenCaps.range.default_value;
    488 #endif
    489                     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    490                         VAProcFilterParameterBufferType, sizeof(sharpen), 1,
    491                         &sharpen, &sharpenId);
    492                     CHECK_VASTATUS("vaCreateBuffer for sharpening");
    493                     mFilterBuffers[mNumFilterBuffers] = sharpenId;
    494                     mNumFilterBuffers++;
    495                 }
    496                 break;
    497             case VAProcFilterColorBalance:
    498                 if((mFilters & FilterColorBalance) != 0) {
    499                     uint32_t featureCount = 0;
    500                     // check filter caps
    501                     // FIXME: it's not used at all!
    502                     numCaps = COLOR_NUM;
    503                     vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
    504                             VAProcFilterColorBalance,
    505                             colorCaps,
    506                             &numCaps);
    507                     CHECK_VASTATUS("vaQueryVideoProcFilterCaps for color balance");
    508                     // create parameter buffer
    509                     for (uint32_t i = 0; i < numCaps; i++) {
    510                         if (colorCaps[i].type == VAProcColorBalanceAutoSaturation) {
    511                             color[i].type = VAProcFilterColorBalance;
    512                             color[i].attrib = VAProcColorBalanceAutoSaturation;
    513                             color[i].value = colorCaps[i].range.min_value + COLOR_STRENGTH * colorCaps[i].range.step;
    514                             featureCount++;
    515                         }
    516                         else if (colorCaps[i].type == VAProcColorBalanceAutoBrightness) {
    517                             color[i].type = VAProcFilterColorBalance;
    518                             color[i].attrib = VAProcColorBalanceAutoBrightness;
    519                             color[i].value = colorCaps[i].range.min_value + COLOR_STRENGTH * colorCaps[i].range.step;
    520                             featureCount++;
    521                         }
    522                     }
    523 #ifdef TARGET_VPP_USE_GEN
    524                     //TODO: VPG need to support check input value by colorCaps.
    525                     enum {kHue = 0, kSaturation, kBrightness, kContrast};
    526                     char propValueString[PROPERTY_VALUE_MAX];
    527                     color[kHue].type = VAProcFilterColorBalance;
    528                     color[kHue].attrib = VAProcColorBalanceHue;
    529 
    530                     // placeholder for vpg driver: can't support auto color balance, so leave config to user.
    531                     property_get("vpp.filter.procamp.hue", propValueString, "179.0");
    532                     color[kHue].value = atof(propValueString);
    533                     color[kHue].value = (color[kHue].value < -180.0f) ? -180.0f : color[kHue].value;
    534                     color[kHue].value = (color[kHue].value > 180.0f) ? 180.0f : color[kHue].value;
    535                     featureCount++;
    536 
    537                     color[kSaturation].type   = VAProcFilterColorBalance;
    538                     color[kSaturation].attrib = VAProcColorBalanceSaturation;
    539                     property_get("vpp.filter.procamp.saturation", propValueString, "1.0");
    540                     color[kSaturation].value = atof(propValueString);
    541                     color[kSaturation].value = (color[kSaturation].value < 0.0f) ? 0.0f : color[kSaturation].value;
    542                     color[kSaturation].value = (color[kSaturation].value > 10.0f) ? 10.0f : color[kSaturation].value;
    543                     featureCount++;
    544 
    545                     color[kBrightness].type   = VAProcFilterColorBalance;
    546                     color[kBrightness].attrib = VAProcColorBalanceBrightness;
    547                     property_get("vpp.filter.procamp.brightness", propValueString, "0.0");
    548                     color[kBrightness].value = atof(propValueString);
    549                     color[kBrightness].value = (color[kBrightness].value < -100.0f) ? -100.0f : color[kBrightness].value;
    550                     color[kBrightness].value = (color[kBrightness].value > 100.0f) ? 100.0f : color[kBrightness].value;
    551                     featureCount++;
    552 
    553                     color[kContrast].type   = VAProcFilterColorBalance;
    554                     color[kContrast].attrib = VAProcColorBalanceContrast;
    555                     property_get("vpp.filter.procamp.contrast", propValueString, "1.0");
    556                     color[kContrast].value = atof(propValueString);
    557                     color[kContrast].value = (color[kContrast].value < 0.0f) ? 0.0f : color[kContrast].value;
    558                     color[kContrast].value = (color[kContrast].value > 10.0f) ? 10.0f : color[kContrast].value;
    559                     featureCount++;
    560 #endif
    561                     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    562                         VAProcFilterParameterBufferType, sizeof(*color), featureCount,
    563                         color, &colorId);
    564                     CHECK_VASTATUS("vaCreateBuffer for color balance");
    565                     mFilterBuffers[mNumFilterBuffers] = colorId;
    566                     mNumFilterBuffers++;
    567                 }
    568                 break;
    569             case VAProcFilterFrameRateConversion:
    570                 if((mFilters & FilterFrameRateConversion) != 0) {
    571                     frc.type = VAProcFilterFrameRateConversion;
    572                     frc.input_fps = mFilterParam.frameRate;
    573                     switch (mFilterParam.frcRate){
    574                         case FRC_RATE_1X:
    575                             frc.output_fps = frc.input_fps;
    576                             break;
    577                         case FRC_RATE_2X:
    578                             frc.output_fps = frc.input_fps * 2;
    579                             break;
    580                         case FRC_RATE_2_5X:
    581                             frc.output_fps = frc.input_fps * 5/2;
    582                             break;
    583                         case FRC_RATE_4X:
    584                             frc.output_fps = frc.input_fps * 4;
    585                             break;
    586                     }
    587                     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    588                         VAProcFilterParameterBufferType, sizeof(frc), 1,
    589                         &frc, &frcId);
    590                     CHECK_VASTATUS("vaCreateBuffer for frc");
    591                     mFilterBuffers[mNumFilterBuffers] = frcId;
    592                     mNumFilterBuffers++;
    593                     mFilterFrc = frcId;
    594                 }
    595                 break;
    596             case VAProcFilterSkinToneEnhancement:
    597                 if((mFilters & FilterSkinToneEnhancement) != 0) {
    598                     // check filter caps
    599                     numCaps = 1;
    600                     vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
    601                             VAProcFilterSkinToneEnhancement,
    602                             &stdeCaps,
    603                             &numCaps);
    604                     CHECK_VASTATUS("vaQueryVideoProcFilterCaps for skintone");
    605                     // create parameter buffer
    606                     stde.type = VAProcFilterSkinToneEnhancement;
    607 #ifdef TARGET_VPP_USE_GEN
    608                     char propValueString[PROPERTY_VALUE_MAX];
    609 
    610                     // placeholder for vpg driver: can't support skintone factor auto adjust, so leave config to user.
    611                     property_get("vpp.filter.skintone.factor", propValueString, "8.0");
    612                     stde.value = atof(propValueString);
    613                     stde.value = (stde.value < 0.0f) ? 0.0f : stde.value;
    614                     stde.value = (stde.value > 8.0f) ? 8.0f : stde.value;
    615 #else
    616                     stde.value = stdeCaps.range.default_value;
    617 #endif
    618                     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    619                         VAProcFilterParameterBufferType, sizeof(stde), 1,
    620                         &stde, &stdeId);
    621                     CHECK_VASTATUS("vaCreateBuffer for skintone");
    622                     mFilterBuffers[mNumFilterBuffers] = stdeId;
    623                     mNumFilterBuffers++;
    624                 }
    625                 break;
    626             default:
    627                 ALOGW("%s: Not supported filter 0x%08x", __func__, supportedFilters[i]);
    628                 break;
    629         }
    630     }
    631 
    632     return setupPipelineCaps();
    633 }
    634 
    635 status_t ISVWorker::setupPipelineCaps() {
    636     ALOGV("setupPipelineCaps");
    637     //TODO color standards
    638     VAProcPipelineCaps pipelineCaps;
    639     VAStatus vaStatus;
    640     pipelineCaps.input_color_standards = in_color_standards;
    641     pipelineCaps.num_input_color_standards = VAProcColorStandardCount;
    642     pipelineCaps.output_color_standards = out_color_standards;
    643     pipelineCaps.num_output_color_standards = VAProcColorStandardCount;
    644 
    645     vaStatus = vaQueryVideoProcPipelineCaps(mVADisplay, mVAContext,
    646         mFilterBuffers, mNumFilterBuffers,
    647         &pipelineCaps);
    648     CHECK_VASTATUS("vaQueryVideoProcPipelineCaps");
    649 
    650     if (mForwardReferences != NULL) {
    651         free(mForwardReferences);
    652         mForwardReferences = NULL;
    653         mNumForwardReferences = 0;
    654     }
    655 
    656     mNumForwardReferences = pipelineCaps.num_forward_references;
    657     if (mNumForwardReferences > 0) {
    658         mForwardReferences = (VASurfaceID*)malloc(mNumForwardReferences * sizeof(VASurfaceID));
    659         if (mForwardReferences == NULL)
    660             return STATUS_ALLOCATION_ERROR;
    661         memset(mForwardReferences, 0, mNumForwardReferences * sizeof(VASurfaceID));
    662     }
    663     return STATUS_OK;
    664 }
    665 
    666 status_t ISVWorker::process(ISVBuffer* inputBuffer, Vector<ISVBuffer*> outputBuffer,
    667                              uint32_t outputCount, bool isEOS, uint32_t flags) {
    668     ALOGV("process: outputCount=%d, mInputIndex=%d", outputCount, mInputIndex);
    669     VASurfaceID input;
    670     VASurfaceID output[MAX_FRC_OUTPUT];
    671     VABufferID pipelineId;
    672     VAProcPipelineParameterBuffer *pipeline;
    673     VAProcFilterParameterBufferFrameRateConversion *frc;
    674     VAStatus vaStatus = STATUS_OK;
    675     uint32_t i = 0;
    676 
    677     if (isEOS) {
    678         if (mInputIndex == 0) {
    679             ALOGV("%s: don't need to flush VSP", __func__);
    680             return STATUS_OK;
    681         }
    682         input = VA_INVALID_SURFACE;
    683         outputCount = 1;
    684         output[0] = mPrevOutput;
    685     } else {
    686         if (!inputBuffer || outputBuffer.size() != outputCount) {
    687             ALOGE("%s: invalid input/output buffer", __func__);
    688             return STATUS_ERROR;
    689         }
    690 
    691         if (outputCount < 1 || outputCount > 4) {
    692             ALOGE("%s: invalid outputCount", __func__);
    693             return STATUS_ERROR;
    694         }
    695 
    696         input = inputBuffer->getSurface();
    697         for (i = 0; i < outputCount; i++) {
    698             output[i] = outputBuffer[i]->getSurface();
    699             if (output[i] == VA_INVALID_SURFACE) {
    700                 ALOGE("invalid output buffer");
    701                 return STATUS_ERROR;
    702             }
    703         }
    704     }
    705 
    706     // reference frames setting
    707     if (mNumForwardReferences > 0) {
    708         /* add previous frame into reference array*/
    709         for (i = 1; i < mNumForwardReferences; i++) {
    710             mForwardReferences[i - 1] = mForwardReferences[i];
    711         }
    712 
    713         //make last reference to input
    714         mForwardReferences[mNumForwardReferences - 1] = mPrevInput;
    715     }
    716 
    717     mPrevInput = input;
    718 
    719     // create pipeline parameter buffer
    720     vaStatus = vaCreateBuffer(mVADisplay,
    721             mVAContext,
    722             VAProcPipelineParameterBufferType,
    723             sizeof(VAProcPipelineParameterBuffer),
    724             1,
    725             NULL,
    726             &pipelineId);
    727     CHECK_VASTATUS("vaCreateBuffer for VAProcPipelineParameterBufferType");
    728 
    729     ALOGV("before vaBeginPicture");
    730     vaStatus = vaBeginPicture(mVADisplay, mVAContext, output[0]);
    731     CHECK_VASTATUS("vaBeginPicture");
    732 
    733     // map pipeline paramter buffer
    734     vaStatus = vaMapBuffer(mVADisplay, pipelineId, (void**)&pipeline);
    735     CHECK_VASTATUS("vaMapBuffer for pipeline parameter buffer");
    736 
    737     // frc pamameter setting
    738     if ((mFilters & FilterFrameRateConversion) != 0) {
    739         vaStatus = vaMapBuffer(mVADisplay, mFilterFrc, (void **)&frc);
    740         CHECK_VASTATUS("vaMapBuffer for frc parameter buffer");
    741         if (isEOS)
    742             frc->num_output_frames = 0;
    743         else
    744             frc->num_output_frames = outputCount - 1;
    745         frc->output_frames = output + 1;
    746     }
    747 
    748     // pipeline parameter setting
    749     VARectangle dst_region;
    750     dst_region.x = 0;
    751     dst_region.y = 0;
    752     dst_region.width = mFilterParam.dstWidth;
    753     dst_region.height = mFilterParam.dstHeight;
    754 
    755     VARectangle src_region;
    756     src_region.x = 0;
    757     src_region.y = 0;
    758     src_region.width = mFilterParam.srcWidth;
    759     src_region.height = mFilterParam.srcHeight;
    760 
    761     if (isEOS) {
    762         pipeline->surface = 0;
    763         pipeline->pipeline_flags = VA_PIPELINE_FLAG_END;
    764     }
    765     else {
    766         pipeline->surface = input;
    767         pipeline->pipeline_flags = 0;
    768     }
    769 #ifdef TARGET_VPP_USE_GEN
    770     pipeline->surface_region = &src_region;
    771     pipeline->output_region = &dst_region;
    772     pipeline->surface_color_standard = VAProcColorStandardBT601;
    773     pipeline->output_color_standard = VAProcColorStandardBT601;
    774 #else
    775     pipeline->surface_region = NULL;
    776     pipeline->output_region = NULL;//&output_region;
    777     pipeline->surface_color_standard = VAProcColorStandardNone;
    778     pipeline->output_color_standard = VAProcColorStandardNone;
    779     /* real rotate state will be decided in psb video */
    780     pipeline->rotation_state = 0;
    781 #endif
    782     /* FIXME: set more meaningful background color */
    783     pipeline->output_background_color = 0;
    784     pipeline->filters = mFilterBuffers;
    785     pipeline->num_filters = mNumFilterBuffers;
    786     pipeline->forward_references = mForwardReferences;
    787     pipeline->num_forward_references = mNumForwardReferences;
    788     pipeline->backward_references = NULL;
    789     pipeline->num_backward_references = 0;
    790 
    791     //currently, we only transfer TOP field to frame, no frame rate change.
    792     if (flags & (OMX_BUFFERFLAG_TFF | OMX_BUFFERFLAG_BFF)) {
    793         pipeline->filter_flags = VA_TOP_FIELD;
    794     } else {
    795         pipeline->filter_flags = VA_FRAME_PICTURE;
    796     }
    797 
    798     if ((mFilters & FilterFrameRateConversion) != 0) {
    799         vaStatus = vaUnmapBuffer(mVADisplay, mFilterFrc);
    800         CHECK_VASTATUS("vaUnmapBuffer for frc parameter buffer");
    801     }
    802 
    803     vaStatus = vaUnmapBuffer(mVADisplay, pipelineId);
    804     CHECK_VASTATUS("vaUnmapBuffer for pipeline parameter buffer");
    805 
    806     ALOGV("before vaRenderPicture");
    807     // Send parameter to driver
    808     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &pipelineId, 1);
    809     CHECK_VASTATUS("vaRenderPicture");
    810 
    811     ALOGV("before vaEndPicture");
    812     vaStatus = vaEndPicture(mVADisplay, mVAContext);
    813     CHECK_VASTATUS("vaEndPicture");
    814 
    815     if (isEOS) {
    816         vaStatus = vaSyncSurface(mVADisplay, mPrevOutput);
    817         CHECK_VASTATUS("vaSyncSurface");
    818         if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, pipelineId)) {
    819             ALOGE("%s: failed to destroy va buffer %d", __func__, pipelineId);
    820             return STATUS_ERROR;
    821         }
    822         return STATUS_OK;
    823     }
    824 
    825     mPrevOutput = output[0];
    826     mInputIndex++;
    827 
    828     Mutex::Autolock autoLock(mPipelineBufferLock);
    829     mPipelineBuffers.push_back(pipelineId);
    830 
    831     ALOGV("process, exit");
    832     return STATUS_OK;
    833 }
    834 
    835 status_t ISVWorker::fill(Vector<ISVBuffer*> outputBuffer, uint32_t outputCount) {
    836     ALOGV("fill, outputCount=%d, mOutputIndex=%d",outputCount, mOutputIndex);
    837     // get output surface
    838     VASurfaceID output[MAX_FRC_OUTPUT];
    839     VAStatus vaStatus;
    840     VASurfaceStatus surStatus;
    841 
    842     if (outputCount < 1)
    843         return STATUS_ERROR;
    844     // map GraphicBuffer to VASurface
    845     for (uint32_t i = 0; i < outputCount; i++) {
    846 
    847         output[i] = outputBuffer[i]->getSurface();
    848         if (output[i] == VA_INVALID_SURFACE) {
    849             ALOGE("invalid output buffer");
    850             return STATUS_ERROR;
    851         }
    852         //FIXME: only enable sync mode
    853 #if 0
    854         vaStatus = vaQuerySurfaceStatus(mVADisplay, output[i],&surStatus);
    855         CHECK_VASTATUS("vaQuerySurfaceStatus");
    856         if (surStatus == VASurfaceRendering) {
    857             ALOGV("Rendering %d", i);
    858             /* The behavior of driver is: all output of one process task are return in one interruption.
    859                The whole outputs of one FRC task are all ready or none of them is ready.
    860                If the behavior changed, it hurts the performance.
    861             */
    862             if (0 != i) {
    863                 ALOGW("*****Driver behavior changed. The performance is hurt.");
    864                 ALOGW("Please check driver behavior: all output of one task return in one interruption.");
    865             }
    866             vaStatus = STATUS_DATA_RENDERING;
    867             break;
    868         }
    869 
    870         if ((surStatus != VASurfaceRendering) && (surStatus != VASurfaceReady)) {
    871             ALOGE("surface statu Error %d", surStatus);
    872             vaStatus = STATUS_ERROR;
    873         }
    874 #endif
    875         vaStatus = vaSyncSurface(mVADisplay, output[i]);
    876         CHECK_VASTATUS("vaSyncSurface");
    877         vaStatus = STATUS_OK;
    878         mOutputCount++;
    879         //dumpYUVFrameData(output[i]);
    880     }
    881 
    882     {
    883         Mutex::Autolock autoLock(mPipelineBufferLock);
    884         if (vaStatus == STATUS_OK) {
    885             VABufferID pipelineBuffer = mPipelineBuffers.itemAt(0);
    886             if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, pipelineBuffer)) {
    887                 ALOGE("%s: failed to destroy va buffer %d", __func__, pipelineBuffer);
    888                 return STATUS_ERROR;
    889             }
    890             mPipelineBuffers.removeAt(0);
    891             mOutputIndex++;
    892         }
    893     }
    894 
    895     ALOGV("fill, exit");
    896     return vaStatus;
    897 }
    898 
    899 // Debug only
    900 #define FRAME_OUTPUT_FILE_NV12 "/storage/sdcard0/vpp_output.nv12"
    901 status_t ISVWorker::dumpYUVFrameData(VASurfaceID surfaceID) {
    902     status_t ret;
    903     if (surfaceID == VA_INVALID_SURFACE)
    904         return STATUS_ERROR;
    905 
    906     VAStatus vaStatus;
    907     VAImage image;
    908     unsigned char *data_ptr;
    909 
    910     vaStatus = vaDeriveImage(mVADisplay,
    911             surfaceID,
    912             &image);
    913     CHECK_VASTATUS("vaDeriveImage");
    914 
    915     vaStatus = vaMapBuffer(mVADisplay, image.buf, (void **)&data_ptr);
    916     CHECK_VASTATUS("vaMapBuffer");
    917 
    918     ret = writeNV12(mFilterParam.srcWidth, mFilterParam.srcHeight, data_ptr, image.pitches[0], image.pitches[1]);
    919     if (ret != STATUS_OK) {
    920         ALOGV("writeNV12 error");
    921         return STATUS_ERROR;
    922     }
    923 
    924     vaStatus = vaUnmapBuffer(mVADisplay, image.buf);
    925     CHECK_VASTATUS("vaUnMapBuffer");
    926 
    927     vaStatus = vaDestroyImage(mVADisplay,image.image_id);
    928     CHECK_VASTATUS("vaDestroyImage");
    929 
    930     return STATUS_OK;
    931 }
    932 
    933 status_t ISVWorker::reset() {
    934     status_t ret;
    935     ALOGV("reset");
    936     if (mOutputCount > 0) {
    937         ALOGI("======mVPPInputCount=%d, mVPPRenderCount=%d======",
    938                 mInputIndex, mOutputCount);
    939     }
    940     mInputIndex = 0;
    941     mOutputIndex = 0;
    942     mOutputCount = 0;
    943 
    944     {
    945         Mutex::Autolock autoLock(mPipelineBufferLock);
    946         while (!mPipelineBuffers.isEmpty()) {
    947             VABufferID pipelineBuffer = mPipelineBuffers.itemAt(0);
    948             if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, pipelineBuffer)) {
    949                 ALOGE("%s: failed to destroy va buffer %d", __func__, pipelineBuffer);
    950                 return STATUS_ERROR;
    951             }
    952             mPipelineBuffers.removeAt(0);
    953         }
    954     }
    955 
    956     if (mNumFilterBuffers != 0) {
    957         for (uint32_t i = 0; i < mNumFilterBuffers; i++) {
    958             if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, mFilterBuffers[i]))
    959                 ALOGW("%s: failed to destroy va buffer %d", __func__, mFilterBuffers[i]);
    960                 //return STATUS_ERROR;
    961         }
    962         mNumFilterBuffers = 0;
    963         memset(&mFilterBuffers, VA_INVALID_ID, VAProcFilterCount * sizeof(VABufferID));
    964         mFilterFrc = VA_INVALID_ID;
    965     }
    966 
    967     // we need to clear the cache for reference surfaces
    968     if (mForwardReferences != NULL) {
    969         free(mForwardReferences);
    970         mForwardReferences = NULL;
    971         mNumForwardReferences = 0;
    972     }
    973 
    974     if (mVAContext != VA_INVALID_ID) {
    975          vaDestroyContext(mVADisplay, mVAContext);
    976          mVAContext = VA_INVALID_ID;
    977     }
    978     VAStatus vaStatus = vaCreateContext(mVADisplay, mVAConfig, mWidth, mHeight, 0, NULL, 0, &mVAContext);
    979     CHECK_VASTATUS("vaCreateContext");
    980 
    981     return setupFilters();
    982 }
    983 
    984 uint32_t ISVWorker::getVppOutputFps() {
    985     uint32_t outputFps;
    986     //mFilterParam.frcRate is 1 if FRC is disabled or input FPS is not changed by VPP.
    987     if (FRC_RATE_2_5X == mFilterParam.frcRate) {
    988         outputFps = mFilterParam.frameRate * 5 / 2;
    989     } else {
    990         outputFps = mFilterParam.frameRate * mFilterParam.frcRate;
    991     }
    992 
    993     ALOGV("vpp is on in settings %d %d %d", outputFps,  mFilterParam.frameRate, mFilterParam.frcRate);
    994     return outputFps;
    995 }
    996 
    997 
    998 status_t ISVWorker::writeNV12(int width, int height, unsigned char *out_buf, int y_pitch, int uv_pitch) {
    999     size_t result;
   1000     int frame_size;
   1001     unsigned char *y_start, *uv_start;
   1002     int h;
   1003 
   1004     FILE *ofile = fopen(FRAME_OUTPUT_FILE_NV12, "ab");
   1005     if(ofile == NULL) {
   1006         ALOGE("Open %s failed!", FRAME_OUTPUT_FILE_NV12);
   1007         return STATUS_ERROR;
   1008     }
   1009 
   1010     if (out_buf == NULL)
   1011     {
   1012         fclose(ofile);
   1013         return STATUS_ERROR;
   1014     }
   1015     if ((width % 2) || (height % 2))
   1016     {
   1017         fclose(ofile);
   1018         return STATUS_ERROR;
   1019     }
   1020     // Set frame size
   1021     frame_size = height * width * 3/2;
   1022 
   1023     /* write y */
   1024     y_start = out_buf;
   1025     for (h = 0; h < height; ++h) {
   1026         result = fwrite(y_start, sizeof(unsigned char), width, ofile);
   1027         y_start += y_pitch;
   1028     }
   1029 
   1030     /* write uv */
   1031     uv_start = out_buf + uv_pitch * height;
   1032     for (h = 0; h < height / 2; ++h) {
   1033         result = fwrite(uv_start, sizeof(unsigned char), width, ofile);
   1034         uv_start += uv_pitch;
   1035     }
   1036     // Close file
   1037     fclose(ofile);
   1038     return STATUS_OK;
   1039 }
   1040 
   1041