Home | History | Annotate | Download | only in videoencoder
      1 /*
      2 * Copyright (c) 2009-2011 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 <string.h>
     18 #include "VideoEncoderLog.h"
     19 #include "VideoEncoderBase.h"
     20 #include "IntelMetadataBuffer.h"
     21 #include <va/va_tpi.h>
     22 #include <va/va_android.h>
     23 
     24 #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
     25 #define max(X,Y) (((X) > (Y)) ? (X) : (Y))
     26 
     27 VideoEncoderBase::VideoEncoderBase()
     28     :mInitialized(true)
     29     ,mStarted(false)
     30     ,mVADisplay(NULL)
     31     ,mVAContext(VA_INVALID_ID)
     32     ,mVAConfig(VA_INVALID_ID)
     33     ,mVAEntrypoint(VAEntrypointEncSlice)
     34     ,mNewHeader(false)
     35     ,mRenderMaxSliceSize(false)
     36     ,mRenderQP (false)
     37     ,mRenderAIR(false)
     38     ,mRenderCIR(false)
     39     ,mRenderFrameRate(false)
     40     ,mRenderBitRate(false)
     41     ,mRenderHrd(false)
     42     ,mRenderMultiTemporal(false)
     43     ,mForceKFrame(false)
     44     ,mSeqParamBuf(0)
     45     ,mPicParamBuf(0)
     46     ,mSliceParamBuf(0)
     47     ,mAutoRefSurfaces(NULL)
     48     ,mRefSurface(VA_INVALID_SURFACE)
     49     ,mRecSurface(VA_INVALID_SURFACE)
     50     ,mFrameNum(0)
     51     ,mCodedBufSize(0)
     52     ,mAutoReference(false)
     53     ,mAutoReferenceSurfaceNum(4)
     54     ,mEncPackedHeaders(VA_ATTRIB_NOT_SUPPORTED)
     55     ,mSliceSizeOverflow(false)
     56     ,mCurOutputTask(NULL)
     57     ,mOutCodedBuffer(0)
     58     ,mOutCodedBufferPtr(NULL)
     59     ,mCurSegment(NULL)
     60     ,mOffsetInSeg(0)
     61     ,mTotalSize(0)
     62     ,mTotalSizeCopied(0)
     63     ,mFrameSkipped(false)
     64     ,mSupportedSurfaceMemType(0)
     65     ,mVASurfaceMappingAction(0)
     66 #ifdef INTEL_VIDEO_XPROC_SHARING
     67     ,mSessionFlag(0)
     68 #endif
     69     {
     70 
     71     VAStatus vaStatus = VA_STATUS_SUCCESS;
     72     // here the display can be any value, use following one
     73     // just for consistence purpose, so don't define it
     74     unsigned int display = 0x18C34078;
     75     int majorVersion = -1;
     76     int minorVersion = -1;
     77 
     78     setDefaultParams();
     79 
     80     LOG_V("vaGetDisplay \n");
     81     mVADisplay = vaGetDisplay(&display);
     82     if (mVADisplay == NULL) {
     83         LOG_E("vaGetDisplay failed.");
     84     }
     85 
     86     vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion);
     87     LOG_V("vaInitialize \n");
     88     if (vaStatus != VA_STATUS_SUCCESS) {
     89         LOG_E( "Failed vaInitialize, vaStatus = %d\n", vaStatus);
     90         mInitialized = false;
     91     }
     92 }
     93 
     94 VideoEncoderBase::~VideoEncoderBase() {
     95 
     96     VAStatus vaStatus = VA_STATUS_SUCCESS;
     97 
     98     stop();
     99 
    100     vaStatus = vaTerminate(mVADisplay);
    101     LOG_V( "vaTerminate\n");
    102     if (vaStatus != VA_STATUS_SUCCESS) {
    103         LOG_W( "Failed vaTerminate, vaStatus = %d\n", vaStatus);
    104     } else {
    105         mVADisplay = NULL;
    106     }
    107 
    108 #ifdef INTEL_VIDEO_XPROC_SHARING
    109     IntelMetadataBuffer::ClearContext(mSessionFlag, false);
    110 #endif
    111 }
    112 
    113 Encode_Status VideoEncoderBase::start() {
    114 
    115     Encode_Status ret = ENCODE_SUCCESS;
    116     VAStatus vaStatus = VA_STATUS_SUCCESS;
    117 
    118     if (!mInitialized) {
    119         LOGE("Encoder Initialize fail can not start");
    120         return ENCODE_DRIVER_FAIL;
    121     }
    122 
    123     if (mStarted) {
    124         LOG_V("Encoder has been started\n");
    125         return ENCODE_ALREADY_INIT;
    126     }
    127 
    128     if (mComParams.rawFormat != RAW_FORMAT_NV12)
    129 #ifdef IMG_GFX
    130         mVASurfaceMappingAction |= MAP_ACTION_COLORCONVERT;
    131 #else
    132         return ENCODE_NOT_SUPPORTED;
    133 #endif
    134 
    135     if (mComParams.resolution.width > 2048 || mComParams.resolution.height > 2048){
    136         LOGE("Unsupported resolution width %d, height %d\n",
    137             mComParams.resolution.width, mComParams.resolution.height);
    138         return ENCODE_NOT_SUPPORTED;
    139     }
    140     queryAutoReferenceConfig(mComParams.profile);
    141 
    142     VAConfigAttrib vaAttrib_tmp[6],vaAttrib[VAConfigAttribTypeMax];
    143     int vaAttribNumber = 0;
    144     vaAttrib_tmp[0].type = VAConfigAttribRTFormat;
    145     vaAttrib_tmp[1].type = VAConfigAttribRateControl;
    146     vaAttrib_tmp[2].type = VAConfigAttribEncAutoReference;
    147     vaAttrib_tmp[3].type = VAConfigAttribEncPackedHeaders;
    148     vaAttrib_tmp[4].type = VAConfigAttribEncMaxRefFrames;
    149     vaAttrib_tmp[5].type = VAConfigAttribEncRateControlExt;
    150 
    151     vaStatus = vaGetConfigAttributes(mVADisplay, mComParams.profile,
    152             VAEntrypointEncSlice, &vaAttrib_tmp[0], 6);
    153     CHECK_VA_STATUS_RETURN("vaGetConfigAttributes");
    154 
    155     if((vaAttrib_tmp[0].value & VA_RT_FORMAT_YUV420) != 0)
    156     {
    157         vaAttrib[vaAttribNumber].type = VAConfigAttribRTFormat;
    158         vaAttrib[vaAttribNumber].value = VA_RT_FORMAT_YUV420;
    159         vaAttribNumber++;
    160     }
    161 
    162     vaAttrib[vaAttribNumber].type = VAConfigAttribRateControl;
    163     vaAttrib[vaAttribNumber].value = mComParams.rcMode;
    164     vaAttribNumber++;
    165 
    166     vaAttrib[vaAttribNumber].type = VAConfigAttribEncAutoReference;
    167     vaAttrib[vaAttribNumber].value = mAutoReference ? 1 : VA_ATTRIB_NOT_SUPPORTED;
    168     vaAttribNumber++;
    169 
    170     if(vaAttrib_tmp[3].value != VA_ATTRIB_NOT_SUPPORTED)
    171     {
    172         vaAttrib[vaAttribNumber].type = VAConfigAttribEncPackedHeaders;
    173         vaAttrib[vaAttribNumber].value = vaAttrib[3].value;
    174         vaAttribNumber++;
    175         mEncPackedHeaders = vaAttrib[3].value;
    176     }
    177 
    178     if(vaAttrib_tmp[4].value != VA_ATTRIB_NOT_SUPPORTED)
    179     {
    180         vaAttrib[vaAttribNumber].type = VAConfigAttribEncMaxRefFrames;
    181         vaAttrib[vaAttribNumber].value = vaAttrib[4].value;
    182         vaAttribNumber++;
    183         mEncMaxRefFrames = vaAttrib[4].value;
    184     }
    185 
    186     if(vaAttrib_tmp[5].value != VA_ATTRIB_NOT_SUPPORTED)
    187     {
    188         vaAttrib[vaAttribNumber].type = VAConfigAttribEncRateControlExt;
    189         vaAttrib[vaAttribNumber].value = mComParams.numberOfLayer;
    190         vaAttribNumber++;
    191     }
    192 
    193     LOG_V( "======VA Configuration======\n");
    194     LOG_V( "profile = %d\n", mComParams.profile);
    195     LOG_V( "mVAEntrypoint = %d\n", mVAEntrypoint);
    196     LOG_V( "vaAttrib[0].type = %d\n", vaAttrib[0].type);
    197     LOG_V( "vaAttrib[1].type = %d\n", vaAttrib[1].type);
    198     LOG_V( "vaAttrib[2].type = %d\n", vaAttrib[2].type);
    199     LOG_V( "vaAttrib[0].value (Format) = %d\n", vaAttrib[0].value);
    200     LOG_V( "vaAttrib[1].value (RC mode) = %d\n", vaAttrib[1].value);
    201     LOG_V( "vaAttrib[2].value (AutoReference) = %d\n", vaAttrib[2].value);
    202     LOG_V( "vaAttribNumber is %d\n", vaAttribNumber);
    203     LOG_V( "mComParams.numberOfLayer is %d\n", mComParams.numberOfLayer);
    204 
    205     LOG_V( "vaCreateConfig\n");
    206 
    207     vaStatus = vaCreateConfig(
    208             mVADisplay, mComParams.profile, mVAEntrypoint,
    209             &vaAttrib[0], vaAttribNumber, &(mVAConfig));
    210 //            &vaAttrib[0], 3, &(mVAConfig));  //uncomment this after psb_video supports
    211     CHECK_VA_STATUS_RETURN("vaCreateConfig");
    212 
    213     querySupportedSurfaceMemTypes();
    214 
    215     if (mComParams.rcMode == VA_RC_VCM) {
    216         // Following three features are only enabled in VCM mode
    217         mRenderMaxSliceSize = true;
    218         mRenderAIR = true;
    219         mRenderBitRate = true;
    220     }
    221 
    222     LOG_V( "======VA Create Surfaces for Rec/Ref frames ======\n");
    223 
    224     uint32_t stride_aligned, height_aligned;
    225     if(mAutoReference == false){
    226         stride_aligned = (mComParams.resolution.width + 15) & ~15;
    227         height_aligned = (mComParams.resolution.height + 15) & ~15;
    228     }else{
    229         // this alignment is used for AVC. For vp8 encode, driver will handle the alignment
    230         if(mComParams.profile == VAProfileVP8Version0_3)
    231         {
    232             stride_aligned = mComParams.resolution.width;
    233             height_aligned = mComParams.resolution.height;
    234             mVASurfaceMappingAction |= MAP_ACTION_COPY;
    235         }
    236         else
    237         {
    238             stride_aligned = (mComParams.resolution.width + 63) & ~63;  //on Merr, stride must be 64 aligned.
    239             height_aligned = (mComParams.resolution.height + 31) & ~31;
    240             mVASurfaceMappingAction |= MAP_ACTION_ALIGN64;
    241         }
    242     }
    243 
    244     if(mAutoReference == false){
    245         mRefSurface = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
    246         mRecSurface = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
    247 
    248     }else {
    249         mAutoRefSurfaces = new VASurfaceID [mAutoReferenceSurfaceNum];
    250         for(uint32_t i = 0; i < mAutoReferenceSurfaceNum; i ++)
    251             mAutoRefSurfaces[i] = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
    252     }
    253     CHECK_VA_STATUS_RETURN("vaCreateSurfaces");
    254 
    255     //Prepare all Surfaces to be added into Context
    256     uint32_t contextSurfaceCnt;
    257     if(mAutoReference == false )
    258         contextSurfaceCnt = 2 + mSrcSurfaceMapList.size();
    259     else
    260         contextSurfaceCnt = mAutoReferenceSurfaceNum + mSrcSurfaceMapList.size();
    261 
    262     VASurfaceID *contextSurfaces = new VASurfaceID[contextSurfaceCnt];
    263     int32_t index = -1;
    264     android::List<VASurfaceMap *>::iterator map_node;
    265 
    266     for(map_node = mSrcSurfaceMapList.begin(); map_node !=  mSrcSurfaceMapList.end(); map_node++)
    267     {
    268         contextSurfaces[++index] = (*map_node)->getVASurface();
    269         (*map_node)->setTracked();
    270     }
    271 
    272     if(mAutoReference == false){
    273         contextSurfaces[++index] = mRefSurface;
    274         contextSurfaces[++index] = mRecSurface;
    275     } else {
    276         for (uint32_t i=0; i < mAutoReferenceSurfaceNum; i++)
    277             contextSurfaces[++index] = mAutoRefSurfaces[i];
    278     }
    279 
    280     //Initialize and save the VA context ID
    281     LOG_V( "vaCreateContext\n");
    282     vaStatus = vaCreateContext(mVADisplay, mVAConfig,
    283 #ifdef IMG_GFX
    284             mComParams.resolution.width,
    285             mComParams.resolution.height,
    286 #else
    287             stride_aligned,
    288             height_aligned,
    289 #endif
    290             VA_PROGRESSIVE, contextSurfaces, contextSurfaceCnt,
    291             &(mVAContext));
    292     CHECK_VA_STATUS_RETURN("vaCreateContext");
    293 
    294     delete [] contextSurfaces;
    295 
    296     LOG_I("Success to create libva context width %d, height %d\n",
    297           mComParams.resolution.width, mComParams.resolution.height);
    298 
    299     uint32_t maxSize = 0;
    300     ret = getMaxOutSize(&maxSize);
    301     CHECK_ENCODE_STATUS_RETURN("getMaxOutSize");
    302 
    303     // Create CodedBuffer for output
    304     VABufferID VACodedBuffer;
    305 
    306     for(uint32_t i = 0; i <mComParams.codedBufNum; i++) {
    307             vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    308                     VAEncCodedBufferType,
    309                     mCodedBufSize,
    310                     1, NULL,
    311                     &VACodedBuffer);
    312             CHECK_VA_STATUS_RETURN("vaCreateBuffer::VAEncCodedBufferType");
    313 
    314             mVACodedBufferList.push_back(VACodedBuffer);
    315     }
    316 
    317     if (ret == ENCODE_SUCCESS)
    318         mStarted = true;
    319 
    320     LOG_V( "end\n");
    321     return ret;
    322 }
    323 
    324 Encode_Status VideoEncoderBase::encode(VideoEncRawBuffer *inBuffer, uint32_t timeout) {
    325 
    326     Encode_Status ret = ENCODE_SUCCESS;
    327     VAStatus vaStatus = VA_STATUS_SUCCESS;
    328 
    329     if (!mStarted) {
    330         LOG_E("Encoder has not initialized yet\n");
    331         return ENCODE_NOT_INIT;
    332     }
    333 
    334     CHECK_NULL_RETURN_IFFAIL(inBuffer);
    335 
    336     //======Prepare all resources encoder needed=====.
    337 
    338     //Prepare encode vaSurface
    339     VASurfaceID sid = VA_INVALID_SURFACE;
    340     ret = manageSrcSurface(inBuffer, &sid);
    341     CHECK_ENCODE_STATUS_RETURN("manageSrcSurface");
    342 
    343     //Prepare CodedBuffer
    344     mCodedBuffer_Lock.lock();
    345     if(mVACodedBufferList.empty()){
    346         if(timeout == FUNC_BLOCK)
    347             mCodedBuffer_Cond.wait(mCodedBuffer_Lock);
    348         else if (timeout > 0) {
    349             if(NO_ERROR != mEncodeTask_Cond.waitRelative(mCodedBuffer_Lock, 1000000*timeout)){
    350                 mCodedBuffer_Lock.unlock();
    351                 LOG_E("Time out wait for Coded buffer.\n");
    352                 return ENCODE_DEVICE_BUSY;
    353             }
    354         }
    355         else {//Nonblock
    356             mCodedBuffer_Lock.unlock();
    357             LOG_E("Coded buffer is not ready now.\n");
    358             return ENCODE_DEVICE_BUSY;
    359         }
    360     }
    361 
    362     if(mVACodedBufferList.empty()){
    363         mCodedBuffer_Lock.unlock();
    364         return ENCODE_DEVICE_BUSY;
    365     }
    366     VABufferID coded_buf = (VABufferID) *(mVACodedBufferList.begin());
    367     mVACodedBufferList.erase(mVACodedBufferList.begin());
    368     mCodedBuffer_Lock.unlock();
    369 
    370     LOG_V("CodedBuffer ID 0x%08x\n", coded_buf);
    371 
    372     //All resources are ready, start to assemble EncodeTask
    373     EncodeTask* task = new EncodeTask();
    374 
    375     task->completed = false;
    376     task->enc_surface = sid;
    377     task->coded_buffer = coded_buf;
    378     task->timestamp = inBuffer->timeStamp;
    379     task->priv = inBuffer->priv;
    380 
    381     //Setup frame info, like flag ( SYNCFRAME), frame number, type etc
    382     task->type = inBuffer->type;
    383     task->flag = inBuffer->flag;
    384     PrepareFrameInfo(task);
    385 
    386     if(mAutoReference == false){
    387         //Setup ref /rec frames
    388         //TODO: B frame support, temporary use same logic
    389         switch (inBuffer->type) {
    390             case FTYPE_UNKNOWN:
    391             case FTYPE_IDR:
    392             case FTYPE_I:
    393             case FTYPE_P:
    394             {
    395                 if(!mFrameSkipped) {
    396                     VASurfaceID tmpSurface = mRecSurface;
    397                     mRecSurface = mRefSurface;
    398                     mRefSurface = tmpSurface;
    399                 }
    400 
    401                 task->ref_surface = mRefSurface;
    402                 task->rec_surface = mRecSurface;
    403 
    404                 break;
    405             }
    406             case FTYPE_B:
    407             default:
    408                 LOG_V("Something wrong, B frame may not be supported in this mode\n");
    409                 ret = ENCODE_NOT_SUPPORTED;
    410                 goto CLEAN_UP;
    411         }
    412     }else {
    413         task->ref_surface = VA_INVALID_SURFACE;
    414         task->rec_surface = VA_INVALID_SURFACE;
    415     }
    416     //======Start Encoding, add task to list======
    417     LOG_V("Start Encoding vaSurface=0x%08x\n", task->enc_surface);
    418 
    419     vaStatus = vaBeginPicture(mVADisplay, mVAContext, task->enc_surface);
    420     CHECK_VA_STATUS_GOTO_CLEANUP("vaBeginPicture");
    421 
    422     ret = sendEncodeCommand(task);
    423     CHECK_ENCODE_STATUS_CLEANUP("sendEncodeCommand");
    424 
    425     vaStatus = vaEndPicture(mVADisplay, mVAContext);
    426     CHECK_VA_STATUS_GOTO_CLEANUP("vaEndPicture");
    427 
    428     LOG_V("Add Task %p into Encode Task list\n", task);
    429     mEncodeTask_Lock.lock();
    430     mEncodeTaskList.push_back(task);
    431     mEncodeTask_Cond.signal();
    432     mEncodeTask_Lock.unlock();
    433 
    434     mFrameNum ++;
    435 
    436     LOG_V("encode return Success\n");
    437 
    438     return ENCODE_SUCCESS;
    439 
    440 CLEAN_UP:
    441 
    442     delete task;
    443     mCodedBuffer_Lock.lock();
    444     mVACodedBufferList.push_back(coded_buf); //push to CodedBuffer pool again since it is not used
    445     mCodedBuffer_Cond.signal();
    446     mCodedBuffer_Lock.unlock();
    447 
    448     LOG_V("encode return error=%x\n", ret);
    449 
    450     return ret;
    451 }
    452 
    453 /*
    454   1. Firstly check if one task is outputting data, if yes, continue outputting, if not try to get one from list.
    455   2. Due to block/non-block/block with timeout 3 modes, if task is not completed, then sync surface, if yes,
    456     start output data
    457   3. Use variable curoutputtask to record task which is getOutput() working on to avoid push again when get failure
    458     on non-block/block with timeout modes.
    459   4. if complete all output data, curoutputtask should be set NULL
    460 */
    461 Encode_Status VideoEncoderBase::getOutput(VideoEncOutputBuffer *outBuffer, uint32_t timeout) {
    462 
    463     Encode_Status ret = ENCODE_SUCCESS;
    464     VAStatus vaStatus = VA_STATUS_SUCCESS;
    465     bool useLocalBuffer = false;
    466 
    467     CHECK_NULL_RETURN_IFFAIL(outBuffer);
    468 
    469     if (mCurOutputTask == NULL) {
    470         mEncodeTask_Lock.lock();
    471         if(mEncodeTaskList.empty()) {
    472             LOG_V("getOutput CurrentTask is NULL\n");
    473             if(timeout == FUNC_BLOCK) {
    474                 LOG_V("waiting for task....\n");
    475                 mEncodeTask_Cond.wait(mEncodeTask_Lock);
    476             } else if (timeout > 0) {
    477                 LOG_V("waiting for task in %i ms....\n", timeout);
    478                 if(NO_ERROR != mEncodeTask_Cond.waitRelative(mEncodeTask_Lock, 1000000*timeout)) {
    479                     mEncodeTask_Lock.unlock();
    480                     LOG_E("Time out wait for encode task.\n");
    481                     return ENCODE_NO_REQUEST_DATA;
    482                 }
    483             } else {//Nonblock
    484                 mEncodeTask_Lock.unlock();
    485                 return ENCODE_NO_REQUEST_DATA;
    486             }
    487         }
    488 
    489         if(mEncodeTaskList.empty()){
    490             mEncodeTask_Lock.unlock();
    491             return ENCODE_DATA_NOT_READY;
    492         }
    493         mCurOutputTask =  *(mEncodeTaskList.begin());
    494         mEncodeTaskList.erase(mEncodeTaskList.begin());
    495         mEncodeTask_Lock.unlock();
    496     }
    497 
    498     //sync/query/wait task if not completed
    499     if (mCurOutputTask->completed == false) {
    500         VASurfaceStatus vaSurfaceStatus;
    501 
    502         if (timeout == FUNC_BLOCK) {
    503             //block mode, direct sync surface to output data
    504 
    505             mOutCodedBuffer = mCurOutputTask->coded_buffer;
    506 
    507             // Check frame skip
    508             // Need encoding to be completed before calling query surface below to
    509             // get the right skip frame flag for current frame
    510             // It is a requirement of video driver
    511             // vaSyncSurface syncs the wrong frame when rendering the same surface multiple times,
    512             // so use vaMapbuffer instead
    513             LOG_V ("block mode, vaMapBuffer ID = 0x%08x\n", mOutCodedBuffer);
    514             if (mOutCodedBufferPtr == NULL) {
    515                 vaStatus = vaMapBuffer (mVADisplay, mOutCodedBuffer, (void **)&mOutCodedBufferPtr);
    516                 CHECK_VA_STATUS_GOTO_CLEANUP("vaMapBuffer");
    517                 CHECK_NULL_RETURN_IFFAIL(mOutCodedBufferPtr);
    518             }
    519 
    520             vaStatus = vaQuerySurfaceStatus(mVADisplay, mCurOutputTask->enc_surface,  &vaSurfaceStatus);
    521             CHECK_VA_STATUS_RETURN("vaQuerySurfaceStatus");
    522             mFrameSkipped = vaSurfaceStatus & VASurfaceSkipped;
    523 
    524             mCurOutputTask->completed = true;
    525 
    526         } else {
    527             //For both block with timeout and non-block mode, query surface, if ready, output data
    528             LOG_V ("non-block mode, vaQuerySurfaceStatus ID = 0x%08x\n", mCurOutputTask->enc_surface);
    529 
    530             vaStatus = vaQuerySurfaceStatus(mVADisplay, mCurOutputTask->enc_surface,  &vaSurfaceStatus);
    531             if (vaSurfaceStatus & VASurfaceReady) {
    532                 mOutCodedBuffer = mCurOutputTask->coded_buffer;
    533                 mFrameSkipped = vaSurfaceStatus & VASurfaceSkipped;
    534                 mCurOutputTask->completed = true;
    535                 //if need to call SyncSurface again ?
    536 
    537             }  else {//not encode complet yet, but keep all context and return directly
    538                 return ENCODE_DATA_NOT_READY;
    539             }
    540 
    541         }
    542 
    543     }
    544 
    545     //start to output data
    546     ret = prepareForOutput(outBuffer, &useLocalBuffer);
    547     CHECK_ENCODE_STATUS_CLEANUP("prepareForOutput");
    548 
    549     //copy all flags to outBuffer
    550     outBuffer->offset = 0;
    551     outBuffer->flag = mCurOutputTask->flag;
    552     outBuffer->type = mCurOutputTask->type;
    553     outBuffer->timeStamp = mCurOutputTask->timestamp;
    554     outBuffer->priv = mCurOutputTask->priv;
    555 
    556     if (outBuffer->format == OUTPUT_EVERYTHING || outBuffer->format == OUTPUT_FRAME_DATA) {
    557         ret = outputAllData(outBuffer);
    558         CHECK_ENCODE_STATUS_CLEANUP("outputAllData");
    559     }else {
    560         ret = getExtFormatOutput(outBuffer);
    561         CHECK_ENCODE_STATUS_CLEANUP("getExtFormatOutput");
    562     }
    563 
    564     LOG_V("out size for this getOutput call = %d\n", outBuffer->dataSize);
    565 
    566     ret = cleanupForOutput();
    567     CHECK_ENCODE_STATUS_CLEANUP("cleanupForOutput");
    568 
    569     LOG_V("getOutput return Success, Frame skip is %d\n", mFrameSkipped);
    570 
    571     return ENCODE_SUCCESS;
    572 
    573 CLEAN_UP:
    574 
    575     if (outBuffer->data && (useLocalBuffer == true)) {
    576         delete[] outBuffer->data;
    577         outBuffer->data = NULL;
    578         useLocalBuffer = false;
    579     }
    580 
    581     if (mOutCodedBufferPtr != NULL) {
    582         vaStatus = vaUnmapBuffer(mVADisplay, mOutCodedBuffer);
    583         mOutCodedBufferPtr = NULL;
    584         mCurSegment = NULL;
    585     }
    586 
    587     delete mCurOutputTask;
    588     mCurOutputTask = NULL;
    589     mCodedBuffer_Lock.lock();
    590     mVACodedBufferList.push_back(mOutCodedBuffer);
    591     mCodedBuffer_Cond.signal();
    592     mCodedBuffer_Lock.unlock();
    593 
    594     LOG_V("getOutput return error=%x\n", ret);
    595     return ret;
    596 }
    597 
    598 void VideoEncoderBase::flush() {
    599 
    600     LOG_V( "Begin\n");
    601 
    602     // reset the properities
    603     mFrameNum = 0;
    604 
    605     LOG_V( "end\n");
    606 }
    607 
    608 Encode_Status VideoEncoderBase::stop() {
    609 
    610     VAStatus vaStatus = VA_STATUS_SUCCESS;
    611     Encode_Status ret = ENCODE_SUCCESS;
    612 
    613     LOG_V( "Begin\n");
    614 
    615     // It is possible that above pointers have been allocated
    616     // before we set mStarted to true
    617     if (!mStarted) {
    618         LOG_V("Encoder has been stopped\n");
    619         return ENCODE_SUCCESS;
    620     }
    621     if (mAutoRefSurfaces) {
    622         delete[] mAutoRefSurfaces;
    623         mAutoRefSurfaces = NULL;
    624     }
    625 
    626     mCodedBuffer_Lock.lock();
    627     mVACodedBufferList.clear();
    628     mCodedBuffer_Lock.unlock();
    629     mCodedBuffer_Cond.broadcast();
    630 
    631     //Delete all uncompleted tasks
    632     mEncodeTask_Lock.lock();
    633     while(! mEncodeTaskList.empty())
    634     {
    635         delete *mEncodeTaskList.begin();
    636         mEncodeTaskList.erase(mEncodeTaskList.begin());
    637     }
    638     mEncodeTask_Lock.unlock();
    639     mEncodeTask_Cond.broadcast();
    640 
    641     //Release Src Surface Buffer Map, destroy surface manually since it is not added into context
    642     LOG_V( "Rlease Src Surface Map\n");
    643     while(! mSrcSurfaceMapList.empty())
    644     {
    645         delete (*mSrcSurfaceMapList.begin());
    646         mSrcSurfaceMapList.erase(mSrcSurfaceMapList.begin());
    647     }
    648 
    649     LOG_V( "vaDestroyContext\n");
    650     if (mVAContext != VA_INVALID_ID) {
    651         vaStatus = vaDestroyContext(mVADisplay, mVAContext);
    652         CHECK_VA_STATUS_GOTO_CLEANUP("vaDestroyContext");
    653     }
    654 
    655     LOG_V( "vaDestroyConfig\n");
    656     if (mVAConfig != VA_INVALID_ID) {
    657         vaStatus = vaDestroyConfig(mVADisplay, mVAConfig);
    658         CHECK_VA_STATUS_GOTO_CLEANUP("vaDestroyConfig");
    659     }
    660 
    661 CLEAN_UP:
    662 
    663     mStarted = false;
    664     mSliceSizeOverflow = false;
    665     mCurOutputTask= NULL;
    666     mOutCodedBuffer = 0;
    667     mCurSegment = NULL;
    668     mOffsetInSeg =0;
    669     mTotalSize = 0;
    670     mTotalSizeCopied = 0;
    671     mFrameSkipped = false;
    672     mSupportedSurfaceMemType = 0;
    673 
    674     LOG_V( "end\n");
    675     return ret;
    676 }
    677 
    678 Encode_Status VideoEncoderBase::prepareForOutput(
    679         VideoEncOutputBuffer *outBuffer, bool *useLocalBuffer) {
    680 
    681     VAStatus vaStatus = VA_STATUS_SUCCESS;
    682     VACodedBufferSegment *vaCodedSeg = NULL;
    683     uint32_t status = 0;
    684 
    685     LOG_V( "begin\n");
    686     // Won't check parameters here as the caller already checked them
    687     // mCurSegment is NULL means it is first time to be here after finishing encoding a frame
    688     if (mCurSegment == NULL) {
    689         if (mOutCodedBufferPtr == NULL) {
    690             vaStatus = vaMapBuffer (mVADisplay, mOutCodedBuffer, (void **)&mOutCodedBufferPtr);
    691             CHECK_VA_STATUS_RETURN("vaMapBuffer");
    692             CHECK_NULL_RETURN_IFFAIL(mOutCodedBufferPtr);
    693         }
    694 
    695         LOG_V("Coded Buffer ID been mapped = 0x%08x\n", mOutCodedBuffer);
    696 
    697         mTotalSize = 0;
    698         mOffsetInSeg = 0;
    699         mTotalSizeCopied = 0;
    700         vaCodedSeg = (VACodedBufferSegment *)mOutCodedBufferPtr;
    701         mCurSegment = (VACodedBufferSegment *)mOutCodedBufferPtr;
    702 
    703         while (1) {
    704 
    705             mTotalSize += vaCodedSeg->size;
    706             status = vaCodedSeg->status;
    707 #ifndef IMG_GFX
    708             uint8_t *pTemp;
    709             uint32_t ii;
    710             pTemp = (uint8_t*)vaCodedSeg->buf;
    711             for(ii = 0; ii < 16;){
    712                 if (*(pTemp + ii) == 0xFF)
    713                     ii++;
    714                 else
    715                     break;
    716             }
    717             if (ii > 0) {
    718                 mOffsetInSeg = ii;
    719             }
    720 #endif
    721             if (!mSliceSizeOverflow) {
    722                 mSliceSizeOverflow = status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
    723             }
    724 
    725             if (vaCodedSeg->next == NULL)
    726                 break;
    727 
    728             vaCodedSeg = (VACodedBufferSegment *)vaCodedSeg->next;
    729         }
    730     }
    731 
    732     // We will support two buffer allocation mode,
    733     // one is application allocates the buffer and passes to encode,
    734     // the other is encode allocate memory
    735 
    736     //means  app doesn't allocate the buffer, so _encode will allocate it.
    737     if (outBuffer->data == NULL) {
    738         *useLocalBuffer = true;
    739         outBuffer->data = new  uint8_t[mTotalSize - mTotalSizeCopied + 100];
    740         if (outBuffer->data == NULL) {
    741             LOG_E( "outBuffer->data == NULL\n");
    742             return ENCODE_NO_MEMORY;
    743         }
    744         outBuffer->bufferSize = mTotalSize + 100;
    745         outBuffer->dataSize = 0;
    746     }
    747 
    748     // Clear all flag for every call
    749     outBuffer->flag = 0;
    750     if (mSliceSizeOverflow) outBuffer->flag |= ENCODE_BUFFERFLAG_SLICEOVERFOLOW;
    751 
    752     if (!mCurSegment)
    753         return ENCODE_FAIL;
    754 
    755     if (mCurSegment->size < mOffsetInSeg) {
    756         LOG_E("mCurSegment->size < mOffsetInSeg\n");
    757         return ENCODE_FAIL;
    758     }
    759 
    760     // Make sure we have data in current segment
    761     if (mCurSegment->size == mOffsetInSeg) {
    762         if (mCurSegment->next != NULL) {
    763             mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
    764             mOffsetInSeg = 0;
    765         } else {
    766             LOG_V("No more data available\n");
    767             outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID;
    768             outBuffer->dataSize = 0;
    769             mCurSegment = NULL;
    770             return ENCODE_NO_REQUEST_DATA;
    771         }
    772     }
    773 
    774     LOG_V( "end\n");
    775     return ENCODE_SUCCESS;
    776 }
    777 
    778 Encode_Status VideoEncoderBase::cleanupForOutput() {
    779 
    780     VAStatus vaStatus = VA_STATUS_SUCCESS;
    781 
    782     //mCurSegment is NULL means all data has been copied out
    783     if (mCurSegment == NULL && mOutCodedBufferPtr) {
    784         vaStatus = vaUnmapBuffer(mVADisplay, mOutCodedBuffer);
    785         CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
    786         mOutCodedBufferPtr = NULL;
    787         mTotalSize = 0;
    788         mOffsetInSeg = 0;
    789         mTotalSizeCopied = 0;
    790 
    791         delete mCurOutputTask;
    792         mCurOutputTask = NULL;
    793         mCodedBuffer_Lock.lock();
    794         mVACodedBufferList.push_back(mOutCodedBuffer);
    795         mCodedBuffer_Cond.signal();
    796         mCodedBuffer_Lock.unlock();
    797 
    798         LOG_V("All data has been outputted, return CodedBuffer 0x%08x to pool\n", mOutCodedBuffer);
    799     }
    800     return ENCODE_SUCCESS;
    801 }
    802 
    803 Encode_Status VideoEncoderBase::queryProfileLevelConfig(VADisplay dpy, VAProfile profile) {
    804 
    805     VAStatus vaStatus = VA_STATUS_SUCCESS;
    806     VAEntrypoint entryPtr[8];
    807     int i, entryPtrNum;
    808 
    809     if(profile ==  VAProfileH264Main) //need to be fixed
    810         return ENCODE_NOT_SUPPORTED;
    811 
    812     vaStatus = vaQueryConfigEntrypoints(dpy, profile, entryPtr, &entryPtrNum);
    813     CHECK_VA_STATUS_RETURN("vaQueryConfigEntrypoints");
    814 
    815     for(i=0; i<entryPtrNum; i++){
    816         if(entryPtr[i] == VAEntrypointEncSlice)
    817             return ENCODE_SUCCESS;
    818     }
    819 
    820     return ENCODE_NOT_SUPPORTED;
    821 }
    822 
    823 Encode_Status VideoEncoderBase::queryAutoReferenceConfig(VAProfile profile) {
    824 
    825     VAStatus vaStatus = VA_STATUS_SUCCESS;
    826     VAConfigAttrib attrib_list;
    827     attrib_list.type = VAConfigAttribEncAutoReference;
    828     attrib_list.value = VA_ATTRIB_NOT_SUPPORTED;
    829 
    830     vaStatus = vaGetConfigAttributes(mVADisplay, profile, VAEntrypointEncSlice, &attrib_list, 1);
    831     CHECK_VA_STATUS_RETURN("vaQueryConfigAttributes");
    832 
    833     if(attrib_list.value == VA_ATTRIB_NOT_SUPPORTED )
    834         mAutoReference = false;
    835     else
    836         mAutoReference = true;
    837 
    838     return ENCODE_SUCCESS;
    839 }
    840 
    841 Encode_Status VideoEncoderBase::querySupportedSurfaceMemTypes() {
    842 
    843     VAStatus vaStatus = VA_STATUS_SUCCESS;
    844 
    845     unsigned int num = 0;
    846 
    847     VASurfaceAttrib* attribs = NULL;
    848 
    849     //get attribs number
    850     vaStatus = vaQuerySurfaceAttributes(mVADisplay, mVAConfig, attribs, &num);
    851     CHECK_VA_STATUS_RETURN("vaGetSurfaceAttributes");
    852 
    853     if (num == 0)
    854         return ENCODE_SUCCESS;
    855 
    856     attribs = new VASurfaceAttrib[num];
    857 
    858     vaStatus = vaQuerySurfaceAttributes(mVADisplay, mVAConfig, attribs, &num);
    859     CHECK_VA_STATUS_RETURN("vaGetSurfaceAttributes");
    860 
    861     for(uint32_t i = 0; i < num; i ++) {
    862         if (attribs[i].type == VASurfaceAttribMemoryType) {
    863             mSupportedSurfaceMemType = attribs[i].value.value.i;
    864             break;
    865         }
    866         else
    867             continue;
    868     }
    869 
    870     delete[] attribs;
    871 
    872     return ENCODE_SUCCESS;
    873 }
    874 
    875 Encode_Status VideoEncoderBase::outputAllData(VideoEncOutputBuffer *outBuffer) {
    876 
    877     // Data size been copied for every single call
    878     uint32_t sizeCopiedHere = 0;
    879     uint32_t sizeToBeCopied = 0;
    880 
    881     CHECK_NULL_RETURN_IFFAIL(outBuffer->data);
    882 
    883     while (1) {
    884 
    885         LOG_V("mCurSegment->size = %d, mOffsetInSeg = %d\n", mCurSegment->size, mOffsetInSeg);
    886         LOG_V("outBuffer->bufferSize = %d, sizeCopiedHere = %d, mTotalSizeCopied = %d\n",
    887               outBuffer->bufferSize, sizeCopiedHere, mTotalSizeCopied);
    888 
    889         if (mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere) {
    890             LOG_E("mCurSegment->size < mOffsetInSeg  || outBuffer->bufferSize < sizeCopiedHere\n");
    891             return ENCODE_FAIL;
    892         }
    893 
    894         if ((mCurSegment->size - mOffsetInSeg) <= outBuffer->bufferSize - sizeCopiedHere) {
    895             sizeToBeCopied = mCurSegment->size - mOffsetInSeg;
    896             memcpy(outBuffer->data + sizeCopiedHere,
    897                    (uint8_t *)mCurSegment->buf + mOffsetInSeg, sizeToBeCopied);
    898             sizeCopiedHere += sizeToBeCopied;
    899             mTotalSizeCopied += sizeToBeCopied;
    900             mOffsetInSeg = 0;
    901         } else {
    902             sizeToBeCopied = outBuffer->bufferSize - sizeCopiedHere;
    903             memcpy(outBuffer->data + sizeCopiedHere,
    904                    (uint8_t *)mCurSegment->buf + mOffsetInSeg, outBuffer->bufferSize - sizeCopiedHere);
    905             mTotalSizeCopied += sizeToBeCopied;
    906             mOffsetInSeg += sizeToBeCopied;
    907             outBuffer->dataSize = outBuffer->bufferSize;
    908             outBuffer->remainingSize = mTotalSize - mTotalSizeCopied;
    909             outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
    910             return ENCODE_BUFFER_TOO_SMALL;
    911         }
    912 
    913         if (mCurSegment->next == NULL) {
    914             outBuffer->dataSize = sizeCopiedHere;
    915             outBuffer->remainingSize = 0;
    916             outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
    917             mCurSegment = NULL;
    918             return ENCODE_SUCCESS;
    919         }
    920 
    921         mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
    922         mOffsetInSeg = 0;
    923     }
    924 }
    925 
    926 void VideoEncoderBase::setDefaultParams() {
    927 
    928     // Set default value for input parameters
    929     mComParams.profile = VAProfileH264Baseline;
    930     mComParams.level = 41;
    931     mComParams.rawFormat = RAW_FORMAT_NV12;
    932     mComParams.frameRate.frameRateNum = 30;
    933     mComParams.frameRate.frameRateDenom = 1;
    934     mComParams.resolution.width = 0;
    935     mComParams.resolution.height = 0;
    936     mComParams.intraPeriod = 30;
    937     mComParams.rcMode = RATE_CONTROL_NONE;
    938     mComParams.rcParams.initQP = 15;
    939     mComParams.rcParams.minQP = 0;
    940     mComParams.rcParams.maxQP = 0;
    941     mComParams.rcParams.I_minQP = 0;
    942     mComParams.rcParams.I_maxQP = 0;
    943     mComParams.rcParams.bitRate = 640000;
    944     mComParams.rcParams.targetPercentage= 0;
    945     mComParams.rcParams.windowSize = 0;
    946     mComParams.rcParams.disableFrameSkip = 0;
    947     mComParams.rcParams.disableBitsStuffing = 1;
    948     mComParams.rcParams.enableIntraFrameQPControl = 0;
    949     mComParams.rcParams.temporalFrameRate = 0;
    950     mComParams.rcParams.temporalID = 0;
    951     mComParams.cyclicFrameInterval = 30;
    952     mComParams.refreshType = VIDEO_ENC_NONIR;
    953     mComParams.airParams.airMBs = 0;
    954     mComParams.airParams.airThreshold = 0;
    955     mComParams.airParams.airAuto = 1;
    956     mComParams.disableDeblocking = 2;
    957     mComParams.syncEncMode = false;
    958     mComParams.codedBufNum = 2;
    959     mComParams.numberOfLayer = 1;
    960     mComParams.nPeriodicity = 0;
    961     memset(mComParams.nLayerID,0,32*sizeof(uint32_t));
    962 
    963     mHrdParam.bufferSize = 0;
    964     mHrdParam.initBufferFullness = 0;
    965 
    966     mStoreMetaDataInBuffers.isEnabled = false;
    967 }
    968 
    969 Encode_Status VideoEncoderBase::setParameters(
    970         VideoParamConfigSet *videoEncParams) {
    971 
    972     Encode_Status ret = ENCODE_SUCCESS;
    973     CHECK_NULL_RETURN_IFFAIL(videoEncParams);
    974     LOG_V("Config type = %x\n", (int)videoEncParams->type);
    975 
    976     if (mStarted) {
    977         LOG_E("Encoder has been initialized, should use setConfig to change configurations\n");
    978         return ENCODE_ALREADY_INIT;
    979     }
    980 
    981     switch (videoEncParams->type) {
    982         case VideoParamsTypeCommon: {
    983 
    984             VideoParamsCommon *paramsCommon =
    985                     reinterpret_cast <VideoParamsCommon *> (videoEncParams);
    986             if (paramsCommon->size != sizeof (VideoParamsCommon)) {
    987                 return ENCODE_INVALID_PARAMS;
    988             }
    989             if(paramsCommon->codedBufNum < 2)
    990                 paramsCommon->codedBufNum =2;
    991             mComParams = *paramsCommon;
    992             break;
    993         }
    994 
    995         case VideoParamsTypeUpSteamBuffer: {
    996 
    997             VideoParamsUpstreamBuffer *upStreamBuffer =
    998                     reinterpret_cast <VideoParamsUpstreamBuffer *> (videoEncParams);
    999 
   1000             if (upStreamBuffer->size != sizeof (VideoParamsUpstreamBuffer)) {
   1001                 return ENCODE_INVALID_PARAMS;
   1002             }
   1003 
   1004             ret = setUpstreamBuffer(upStreamBuffer);
   1005             break;
   1006         }
   1007 
   1008         case VideoParamsTypeUsrptrBuffer: {
   1009 
   1010             // usrptr only can be get
   1011             // this case should not happen
   1012             break;
   1013         }
   1014 
   1015         case VideoParamsTypeHRD: {
   1016             VideoParamsHRD *hrd =
   1017                     reinterpret_cast <VideoParamsHRD *> (videoEncParams);
   1018 
   1019             if (hrd->size != sizeof (VideoParamsHRD)) {
   1020                 return ENCODE_INVALID_PARAMS;
   1021             }
   1022 
   1023             mHrdParam.bufferSize = hrd->bufferSize;
   1024             mHrdParam.initBufferFullness = hrd->initBufferFullness;
   1025             mRenderHrd = true;
   1026 
   1027             break;
   1028         }
   1029 
   1030         case VideoParamsTypeStoreMetaDataInBuffers: {
   1031             VideoParamsStoreMetaDataInBuffers *metadata =
   1032                     reinterpret_cast <VideoParamsStoreMetaDataInBuffers *> (videoEncParams);
   1033 
   1034             if (metadata->size != sizeof (VideoParamsStoreMetaDataInBuffers)) {
   1035                 return ENCODE_INVALID_PARAMS;
   1036             }
   1037 
   1038             mStoreMetaDataInBuffers.isEnabled = metadata->isEnabled;
   1039 
   1040             break;
   1041         }
   1042 
   1043         case VideoParamsTypeTemporalLayer:{
   1044             VideoParamsTemporalLayer *temporallayer =
   1045                     reinterpret_cast <VideoParamsTemporalLayer *> (videoEncParams);
   1046 
   1047             if (temporallayer->size != sizeof(VideoParamsTemporalLayer)) {
   1048                  return ENCODE_INVALID_PARAMS;
   1049             }
   1050 
   1051             mComParams.numberOfLayer = temporallayer->numberOfLayer;
   1052             mComParams.nPeriodicity = temporallayer->nPeriodicity;
   1053             for(uint32_t i=0;i<temporallayer->nPeriodicity;i++)
   1054                 mComParams.nLayerID[i] = temporallayer->nLayerID[i];
   1055             mRenderMultiTemporal = true;
   1056             break;
   1057         }
   1058 
   1059         case VideoParamsTypeAVC:
   1060         case VideoParamsTypeH263:
   1061         case VideoParamsTypeMP4:
   1062         case VideoParamsTypeVC1:
   1063         case VideoParamsTypeVP8: {
   1064             ret = derivedSetParams(videoEncParams);
   1065             break;
   1066         }
   1067 
   1068         default: {
   1069             LOG_E ("Wrong ParamType here\n");
   1070             return ENCODE_INVALID_PARAMS;
   1071         }
   1072     }
   1073     return ret;
   1074 }
   1075 
   1076 Encode_Status VideoEncoderBase::getParameters(
   1077         VideoParamConfigSet *videoEncParams) {
   1078 
   1079     Encode_Status ret = ENCODE_SUCCESS;
   1080     CHECK_NULL_RETURN_IFFAIL(videoEncParams);
   1081     LOG_V("Config type = %d\n", (int)videoEncParams->type);
   1082 
   1083     switch (videoEncParams->type) {
   1084         case VideoParamsTypeCommon: {
   1085 
   1086             VideoParamsCommon *paramsCommon =
   1087                     reinterpret_cast <VideoParamsCommon *> (videoEncParams);
   1088 
   1089             if (paramsCommon->size != sizeof (VideoParamsCommon)) {
   1090                 return ENCODE_INVALID_PARAMS;
   1091             }
   1092             *paramsCommon = mComParams;
   1093             break;
   1094         }
   1095 
   1096         case VideoParamsTypeUpSteamBuffer: {
   1097 
   1098             // Get upstream buffer could happen
   1099             // but not meaningful a lot
   1100             break;
   1101         }
   1102 
   1103         case VideoParamsTypeUsrptrBuffer: {
   1104             VideoParamsUsrptrBuffer *usrptrBuffer =
   1105                     reinterpret_cast <VideoParamsUsrptrBuffer *> (videoEncParams);
   1106 
   1107             if (usrptrBuffer->size != sizeof (VideoParamsUsrptrBuffer)) {
   1108                 return ENCODE_INVALID_PARAMS;
   1109             }
   1110 
   1111             ret = getNewUsrptrFromSurface(
   1112                     usrptrBuffer->width, usrptrBuffer->height, usrptrBuffer->format,
   1113                     usrptrBuffer->expectedSize, &(usrptrBuffer->actualSize),
   1114                     &(usrptrBuffer->stride), &(usrptrBuffer->usrPtr));
   1115 
   1116             break;
   1117         }
   1118 
   1119         case VideoParamsTypeHRD: {
   1120             VideoParamsHRD *hrd =
   1121                     reinterpret_cast <VideoParamsHRD *> (videoEncParams);
   1122 
   1123             if (hrd->size != sizeof (VideoParamsHRD)) {
   1124                 return ENCODE_INVALID_PARAMS;
   1125             }
   1126 
   1127             hrd->bufferSize = mHrdParam.bufferSize;
   1128             hrd->initBufferFullness = mHrdParam.initBufferFullness;
   1129 
   1130             break;
   1131         }
   1132 
   1133         case VideoParamsTypeStoreMetaDataInBuffers: {
   1134             VideoParamsStoreMetaDataInBuffers *metadata =
   1135                     reinterpret_cast <VideoParamsStoreMetaDataInBuffers *> (videoEncParams);
   1136 
   1137             if (metadata->size != sizeof (VideoParamsStoreMetaDataInBuffers)) {
   1138                 return ENCODE_INVALID_PARAMS;
   1139             }
   1140 
   1141             metadata->isEnabled = mStoreMetaDataInBuffers.isEnabled;
   1142 
   1143             break;
   1144         }
   1145 
   1146         case VideoParamsTypeProfileLevel: {
   1147             VideoParamsProfileLevel *profilelevel =
   1148                 reinterpret_cast <VideoParamsProfileLevel *> (videoEncParams);
   1149 
   1150             if (profilelevel->size != sizeof (VideoParamsProfileLevel)) {
   1151                 return ENCODE_INVALID_PARAMS;
   1152             }
   1153 
   1154             profilelevel->level = 0;
   1155             if(queryProfileLevelConfig(mVADisplay, profilelevel->profile) == ENCODE_SUCCESS){
   1156                 profilelevel->isSupported = true;
   1157                 if(profilelevel->profile == VAProfileH264High)
   1158                     profilelevel->level = 42;
   1159                 else if(profilelevel->profile == VAProfileH264Main)
   1160                      profilelevel->level = 42;
   1161                 else if(profilelevel->profile == VAProfileH264Baseline)
   1162                      profilelevel->level = 41;
   1163                 else{
   1164                     profilelevel->level = 0;
   1165                     profilelevel->isSupported = false;
   1166                 }
   1167             }
   1168         }
   1169 
   1170         case VideoParamsTypeTemporalLayer:{
   1171             VideoParamsTemporalLayer *temporallayer =
   1172                 reinterpret_cast <VideoParamsTemporalLayer *> (videoEncParams);
   1173 
   1174             if(temporallayer->size != sizeof(VideoParamsTemporalLayer)) {
   1175                 return ENCODE_INVALID_PARAMS;
   1176             }
   1177 
   1178             temporallayer->numberOfLayer = mComParams.numberOfLayer;
   1179 
   1180             break;
   1181         }
   1182 
   1183         case VideoParamsTypeAVC:
   1184         case VideoParamsTypeH263:
   1185         case VideoParamsTypeMP4:
   1186         case VideoParamsTypeVC1:
   1187         case VideoParamsTypeVP8: {
   1188             derivedGetParams(videoEncParams);
   1189             break;
   1190         }
   1191 
   1192         default: {
   1193             LOG_E ("Wrong ParamType here\n");
   1194             break;
   1195         }
   1196 
   1197     }
   1198     return ret;
   1199 }
   1200 
   1201 Encode_Status VideoEncoderBase::setConfig(VideoParamConfigSet *videoEncConfig) {
   1202 
   1203     Encode_Status ret = ENCODE_SUCCESS;
   1204     CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
   1205     LOG_V("Config type = %d\n", (int)videoEncConfig->type);
   1206 
   1207    // workaround
   1208 #if 0
   1209     if (!mStarted) {
   1210         LOG_E("Encoder has not initialized yet, can't call setConfig\n");
   1211         return ENCODE_NOT_INIT;
   1212     }
   1213 #endif
   1214 
   1215     switch (videoEncConfig->type) {
   1216         case VideoConfigTypeFrameRate: {
   1217             VideoConfigFrameRate *configFrameRate =
   1218                     reinterpret_cast <VideoConfigFrameRate *> (videoEncConfig);
   1219 
   1220             if (configFrameRate->size != sizeof (VideoConfigFrameRate)) {
   1221                 return ENCODE_INVALID_PARAMS;
   1222             }
   1223             mComParams.frameRate = configFrameRate->frameRate;
   1224             mRenderFrameRate = true;
   1225             break;
   1226         }
   1227 
   1228         case VideoConfigTypeBitRate: {
   1229             VideoConfigBitRate *configBitRate =
   1230                     reinterpret_cast <VideoConfigBitRate *> (videoEncConfig);
   1231 
   1232             if (configBitRate->size != sizeof (VideoConfigBitRate)) {
   1233                 return ENCODE_INVALID_PARAMS;
   1234             }
   1235 
   1236             if(mComParams.numberOfLayer == 1)
   1237             {
   1238                 mComParams.rcParams = configBitRate->rcParams;
   1239                 mRenderBitRate = true;
   1240             }
   1241             else
   1242             {
   1243                 mTemporalLayerBitrateFramerate[configBitRate->rcParams.temporalID].nLayerID = configBitRate->rcParams.temporalID;
   1244                 mTemporalLayerBitrateFramerate[configBitRate->rcParams.temporalID].bitRate = configBitRate->rcParams.bitRate;
   1245                 mTemporalLayerBitrateFramerate[configBitRate->rcParams.temporalID].frameRate = configBitRate->rcParams.temporalFrameRate;
   1246             }
   1247             break;
   1248         }
   1249 
   1250         case VideoConfigTypeResolution: {
   1251 
   1252             // Not Implemented
   1253             break;
   1254         }
   1255         case VideoConfigTypeIntraRefreshType: {
   1256 
   1257             VideoConfigIntraRefreshType *configIntraRefreshType =
   1258                     reinterpret_cast <VideoConfigIntraRefreshType *> (videoEncConfig);
   1259 
   1260             if (configIntraRefreshType->size != sizeof (VideoConfigIntraRefreshType)) {
   1261                 return ENCODE_INVALID_PARAMS;
   1262             }
   1263             mComParams.refreshType = configIntraRefreshType->refreshType;
   1264             break;
   1265         }
   1266 
   1267         case VideoConfigTypeCyclicFrameInterval: {
   1268             VideoConfigCyclicFrameInterval *configCyclicFrameInterval =
   1269                     reinterpret_cast <VideoConfigCyclicFrameInterval *> (videoEncConfig);
   1270             if (configCyclicFrameInterval->size != sizeof (VideoConfigCyclicFrameInterval)) {
   1271                 return ENCODE_INVALID_PARAMS;
   1272             }
   1273 
   1274             mComParams.cyclicFrameInterval = configCyclicFrameInterval->cyclicFrameInterval;
   1275             break;
   1276         }
   1277 
   1278         case VideoConfigTypeAIR: {
   1279 
   1280             VideoConfigAIR *configAIR = reinterpret_cast <VideoConfigAIR *> (videoEncConfig);
   1281 
   1282             if (configAIR->size != sizeof (VideoConfigAIR)) {
   1283                 return ENCODE_INVALID_PARAMS;
   1284             }
   1285 
   1286             mComParams.airParams = configAIR->airParams;
   1287             mRenderAIR = true;
   1288             break;
   1289         }
   1290         case VideoConfigTypeCIR: {
   1291 
   1292             VideoConfigCIR *configCIR = reinterpret_cast <VideoConfigCIR *> (videoEncConfig);
   1293 
   1294             if (configCIR->size != sizeof (VideoConfigCIR)) {
   1295                 return ENCODE_INVALID_PARAMS;
   1296             }
   1297 
   1298             mComParams.cirParams = configCIR->cirParams;
   1299             mRenderCIR = true;
   1300             break;
   1301         }
   1302         case VideoConfigTypeAVCIntraPeriod:
   1303         case VideoConfigTypeNALSize:
   1304         case VideoConfigTypeIDRRequest:
   1305         case VideoConfigTypeSliceNum:
   1306         case VideoConfigTypeVP8:
   1307         case VideoConfigTypeVP8ReferenceFrame:
   1308         case VideoConfigTypeVP8MaxFrameSizeRatio:{
   1309             ret = derivedSetConfig(videoEncConfig);
   1310             break;
   1311         }
   1312         default: {
   1313             LOG_E ("Wrong Config Type here\n");
   1314             break;
   1315         }
   1316     }
   1317     return ret;
   1318 }
   1319 
   1320 Encode_Status VideoEncoderBase::getConfig(VideoParamConfigSet *videoEncConfig) {
   1321 
   1322     Encode_Status ret = ENCODE_SUCCESS;
   1323     CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
   1324     LOG_V("Config type = %d\n", (int)videoEncConfig->type);
   1325 
   1326     switch (videoEncConfig->type) {
   1327         case VideoConfigTypeFrameRate: {
   1328             VideoConfigFrameRate *configFrameRate =
   1329                     reinterpret_cast <VideoConfigFrameRate *> (videoEncConfig);
   1330 
   1331             if (configFrameRate->size != sizeof (VideoConfigFrameRate)) {
   1332                 return ENCODE_INVALID_PARAMS;
   1333             }
   1334 
   1335             configFrameRate->frameRate = mComParams.frameRate;
   1336             break;
   1337         }
   1338 
   1339         case VideoConfigTypeBitRate: {
   1340             VideoConfigBitRate *configBitRate =
   1341                     reinterpret_cast <VideoConfigBitRate *> (videoEncConfig);
   1342 
   1343             if (configBitRate->size != sizeof (VideoConfigBitRate)) {
   1344                 return ENCODE_INVALID_PARAMS;
   1345             }
   1346             configBitRate->rcParams = mComParams.rcParams;
   1347 
   1348 
   1349             break;
   1350         }
   1351         case VideoConfigTypeResolution: {
   1352             // Not Implemented
   1353             break;
   1354         }
   1355         case VideoConfigTypeIntraRefreshType: {
   1356 
   1357             VideoConfigIntraRefreshType *configIntraRefreshType =
   1358                     reinterpret_cast <VideoConfigIntraRefreshType *> (videoEncConfig);
   1359 
   1360             if (configIntraRefreshType->size != sizeof (VideoConfigIntraRefreshType)) {
   1361                 return ENCODE_INVALID_PARAMS;
   1362             }
   1363             configIntraRefreshType->refreshType = mComParams.refreshType;
   1364             break;
   1365         }
   1366 
   1367         case VideoConfigTypeCyclicFrameInterval: {
   1368             VideoConfigCyclicFrameInterval *configCyclicFrameInterval =
   1369                     reinterpret_cast <VideoConfigCyclicFrameInterval *> (videoEncConfig);
   1370             if (configCyclicFrameInterval->size != sizeof (VideoConfigCyclicFrameInterval)) {
   1371                 return ENCODE_INVALID_PARAMS;
   1372             }
   1373 
   1374             configCyclicFrameInterval->cyclicFrameInterval = mComParams.cyclicFrameInterval;
   1375             break;
   1376         }
   1377 
   1378         case VideoConfigTypeAIR: {
   1379 
   1380             VideoConfigAIR *configAIR = reinterpret_cast <VideoConfigAIR *> (videoEncConfig);
   1381 
   1382             if (configAIR->size != sizeof (VideoConfigAIR)) {
   1383                 return ENCODE_INVALID_PARAMS;
   1384             }
   1385 
   1386             configAIR->airParams = mComParams.airParams;
   1387             break;
   1388         }
   1389         case VideoConfigTypeCIR: {
   1390 
   1391             VideoConfigCIR *configCIR = reinterpret_cast <VideoConfigCIR *> (videoEncConfig);
   1392 
   1393             if (configCIR->size != sizeof (VideoConfigCIR)) {
   1394                 return ENCODE_INVALID_PARAMS;
   1395             }
   1396 
   1397             configCIR->cirParams = mComParams.cirParams;
   1398             break;
   1399         }
   1400         case VideoConfigTypeAVCIntraPeriod:
   1401         case VideoConfigTypeNALSize:
   1402         case VideoConfigTypeIDRRequest:
   1403         case VideoConfigTypeSliceNum:
   1404         case VideoConfigTypeVP8: {
   1405 
   1406             ret = derivedGetConfig(videoEncConfig);
   1407             break;
   1408         }
   1409         default: {
   1410             LOG_E ("Wrong ParamType here\n");
   1411             break;
   1412         }
   1413     }
   1414     return ret;
   1415 }
   1416 
   1417 void VideoEncoderBase:: PrepareFrameInfo (EncodeTask* task) {
   1418     if (mNewHeader) mFrameNum = 0;
   1419     LOG_V( "mFrameNum = %d   ", mFrameNum);
   1420 
   1421     updateFrameInfo(task) ;
   1422 }
   1423 
   1424 Encode_Status VideoEncoderBase:: updateFrameInfo (EncodeTask* task) {
   1425 
   1426     task->type = FTYPE_P;
   1427 
   1428     // determine the picture type
   1429     if (mFrameNum == 0)
   1430         task->type = FTYPE_I;
   1431     if (mComParams.intraPeriod != 0 && ((mFrameNum % mComParams.intraPeriod) == 0))
   1432         task->type = FTYPE_I;
   1433 
   1434     if (task->type == FTYPE_I)
   1435         task->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
   1436 
   1437     return ENCODE_SUCCESS;
   1438 }
   1439 
   1440 Encode_Status  VideoEncoderBase::getMaxOutSize (uint32_t *maxSize) {
   1441 
   1442     uint32_t size = mComParams.resolution.width * mComParams.resolution.height;
   1443 
   1444     if (maxSize == NULL) {
   1445         LOG_E("maxSize == NULL\n");
   1446         return ENCODE_NULL_PTR;
   1447     }
   1448 
   1449     LOG_V( "Begin\n");
   1450 
   1451     if (mCodedBufSize > 0) {
   1452         *maxSize = mCodedBufSize;
   1453         LOG_V ("Already calculate the max encoded size, get the value directly");
   1454         return ENCODE_SUCCESS;
   1455     }
   1456 
   1457     // here, VP8 is different from AVC/H263
   1458     if(mComParams.profile == VAProfileVP8Version0_3) // for VP8 encode
   1459     {
   1460         // According to VIED suggestions, in CBR mode, coded buffer should be the size of 3 bytes per luma pixel
   1461         // in CBR_HRD mode, coded buffer size should be  5 * rc_buf_sz * rc_target_bitrate;
   1462         // now we just hardcode mCodedBufSize as 2M to walk round coded buffer size issue;
   1463         /*
   1464         if(mComParams.rcMode == VA_RC_CBR) // CBR_HRD mode
   1465             mCodedBufSize = 5 * mComParams.rcParams.bitRate * 6000;
   1466         else // CBR mode
   1467             mCodedBufSize = 3 * mComParams.resolution.width * mComParams.resolution.height;
   1468         */
   1469         mCodedBufSize = (2 * 1024 * 1024 + 31) & (~31);
   1470     }
   1471     else // for AVC/H263/MPEG4 encode
   1472     {
   1473         // base on the rate control mode to calculate the defaule encoded buffer size
   1474         if (mComParams.rcMode == VA_RC_NONE) {
   1475              mCodedBufSize = (size * 400) / (16 * 16);
   1476              // set to value according to QP
   1477         } else {
   1478              mCodedBufSize = mComParams.rcParams.bitRate / 4;
   1479         }
   1480 
   1481         mCodedBufSize = max (mCodedBufSize , (size * 400) / (16 * 16));
   1482 
   1483         // in case got a very large user input bit rate value
   1484         mCodedBufSize = min(mCodedBufSize, (size * 1.5 * 8));
   1485         mCodedBufSize =  (mCodedBufSize + 15) &(~15);
   1486     }
   1487 
   1488     *maxSize = mCodedBufSize;
   1489     return ENCODE_SUCCESS;
   1490 }
   1491 
   1492 Encode_Status VideoEncoderBase::getNewUsrptrFromSurface(
   1493     uint32_t width, uint32_t height, uint32_t format,
   1494     uint32_t expectedSize, uint32_t *outsize, uint32_t *stride, uint8_t **usrptr) {
   1495 
   1496     Encode_Status ret = ENCODE_FAIL;
   1497     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1498 
   1499     VASurfaceID surface = VA_INVALID_SURFACE;
   1500     VAImage image;
   1501     uint32_t index = 0;
   1502 
   1503     LOG_V( "Begin\n");
   1504     // If encode session has been configured, we can not request surface creation anymore
   1505     if (mStarted) {
   1506         LOG_E( "Already Initialized, can not request VA surface anymore\n");
   1507         return ENCODE_WRONG_STATE;
   1508     }
   1509     if (width<=0 || height<=0 ||outsize == NULL ||stride == NULL || usrptr == NULL) {
   1510         LOG_E("width<=0 || height<=0 || outsize == NULL || stride == NULL ||usrptr == NULL\n");
   1511         return ENCODE_NULL_PTR;
   1512     }
   1513 
   1514     // Current only NV12 is supported in VA API
   1515     // Through format we can get known the number of planes
   1516     if (format != STRING_TO_FOURCC("NV12")) {
   1517         LOG_W ("Format is not supported\n");
   1518         return ENCODE_NOT_SUPPORTED;
   1519     }
   1520 
   1521     surface = CreateNewVASurface(mVADisplay, width, height);
   1522     if (surface == VA_INVALID_SURFACE)
   1523         return ENCODE_DRIVER_FAIL;
   1524 
   1525     vaStatus = vaDeriveImage(mVADisplay, surface, &image);
   1526     CHECK_VA_STATUS_RETURN("vaDeriveImage");
   1527     LOG_V( "vaDeriveImage Done\n");
   1528     vaStatus = vaMapBuffer(mVADisplay, image.buf, (void **) usrptr);
   1529     CHECK_VA_STATUS_RETURN("vaMapBuffer");
   1530 
   1531     // make sure the physical page been allocated
   1532     for (index = 0; index < image.data_size; index = index + 4096) {
   1533         unsigned char tmp =  *(*usrptr + index);
   1534         if (tmp == 0)
   1535             *(*usrptr + index) = 0;
   1536     }
   1537 
   1538     *outsize = image.data_size;
   1539     *stride = image.pitches[0];
   1540 
   1541     LOG_V( "surface = 0x%08x\n",(uint32_t)surface);
   1542     LOG_V("image->pitches[0] = %d\n", image.pitches[0]);
   1543     LOG_V("image->pitches[1] = %d\n", image.pitches[1]);
   1544     LOG_V("image->offsets[0] = %d\n", image.offsets[0]);
   1545     LOG_V("image->offsets[1] = %d\n", image.offsets[1]);
   1546     LOG_V("image->num_planes = %d\n", image.num_planes);
   1547     LOG_V("image->width = %d\n", image.width);
   1548     LOG_V("image->height = %d\n", image.height);
   1549     LOG_V("data_size = %d\n", image.data_size);
   1550     LOG_V("usrptr = 0x%p\n", *usrptr);
   1551 
   1552     vaStatus = vaUnmapBuffer(mVADisplay, image.buf);
   1553     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
   1554     vaStatus = vaDestroyImage(mVADisplay, image.image_id);
   1555     CHECK_VA_STATUS_RETURN("vaDestroyImage");
   1556 
   1557     if (*outsize < expectedSize) {
   1558         LOG_E ("Allocated buffer size is small than the expected size, destroy the surface");
   1559         LOG_I ("Allocated size is %d, expected size is %d\n", *outsize, expectedSize);
   1560         vaStatus = vaDestroySurfaces(mVADisplay, &surface, 1);
   1561         CHECK_VA_STATUS_RETURN("vaDestroySurfaces");
   1562         return ENCODE_FAIL;
   1563     }
   1564 
   1565     VASurfaceMap *map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
   1566     if (map == NULL) {
   1567         LOG_E( "new VASurfaceMap failed\n");
   1568         return ENCODE_NO_MEMORY;
   1569     }
   1570 
   1571     map->setVASurface(surface);  //special case, vasuface is set, so nothing do in doMapping
   1572 //    map->setType(MetadataBufferTypeEncoder);
   1573     map->setValue((intptr_t)*usrptr);
   1574     ValueInfo vinfo;
   1575     memset(&vinfo, 0, sizeof(ValueInfo));
   1576     vinfo.mode = (MemMode)MEM_MODE_USRPTR;
   1577     vinfo.handle = 0;
   1578     vinfo.size = 0;
   1579     vinfo.width = width;
   1580     vinfo.height = height;
   1581     vinfo.lumaStride = width;
   1582     vinfo.chromStride = width;
   1583     vinfo.format = VA_FOURCC_NV12;
   1584     vinfo.s3dformat = 0xffffffff;
   1585     map->setValueInfo(vinfo);
   1586     map->doMapping();
   1587 
   1588     mSrcSurfaceMapList.push_back(map);
   1589 
   1590     ret = ENCODE_SUCCESS;
   1591 
   1592     return ret;
   1593 }
   1594 
   1595 Encode_Status VideoEncoderBase::setUpstreamBuffer(VideoParamsUpstreamBuffer *upStreamBuffer) {
   1596 
   1597     Encode_Status status = ENCODE_SUCCESS;
   1598 
   1599     CHECK_NULL_RETURN_IFFAIL(upStreamBuffer);
   1600     if (upStreamBuffer->bufCnt == 0) {
   1601         LOG_E("bufCnt == 0\n");
   1602         return ENCODE_FAIL;
   1603     }
   1604 
   1605     for(unsigned int i=0; i < upStreamBuffer->bufCnt; i++) {
   1606         if (findSurfaceMapByValue(upStreamBuffer->bufList[i]) != NULL)  //already mapped
   1607             continue;
   1608 
   1609         //wrap upstream buffer into vaSurface
   1610         VASurfaceMap *map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
   1611 
   1612 //        map->setType(MetadataBufferTypeUser);
   1613         map->setValue(upStreamBuffer->bufList[i]);
   1614         ValueInfo vinfo;
   1615         memset(&vinfo, 0, sizeof(ValueInfo));
   1616         vinfo.mode = (MemMode)upStreamBuffer->bufferMode;
   1617         vinfo.handle = (intptr_t)upStreamBuffer->display;
   1618         vinfo.size = 0;
   1619         if (upStreamBuffer->bufAttrib) {
   1620             vinfo.width = upStreamBuffer->bufAttrib->realWidth;
   1621             vinfo.height = upStreamBuffer->bufAttrib->realHeight;
   1622             vinfo.lumaStride = upStreamBuffer->bufAttrib->lumaStride;
   1623             vinfo.chromStride = upStreamBuffer->bufAttrib->chromStride;
   1624             vinfo.format = upStreamBuffer->bufAttrib->format;
   1625         }
   1626         vinfo.s3dformat = 0xFFFFFFFF;
   1627         map->setValueInfo(vinfo);
   1628         status = map->doMapping();
   1629 
   1630         if (status == ENCODE_SUCCESS)
   1631             mSrcSurfaceMapList.push_back(map);
   1632         else
   1633            delete map;
   1634     }
   1635 
   1636     return status;
   1637 }
   1638 
   1639 Encode_Status VideoEncoderBase::manageSrcSurface(VideoEncRawBuffer *inBuffer, VASurfaceID *sid) {
   1640 
   1641     Encode_Status ret = ENCODE_SUCCESS;
   1642     IntelMetadataBufferType type;
   1643     intptr_t value;
   1644     ValueInfo vinfo;
   1645     ValueInfo *pvinfo = &vinfo;
   1646     intptr_t *extravalues = NULL;
   1647     unsigned int extravalues_count = 0;
   1648 
   1649     IntelMetadataBuffer imb;
   1650     VASurfaceMap *map = NULL;
   1651 
   1652     memset(&vinfo, 0, sizeof(ValueInfo));
   1653     if (mStoreMetaDataInBuffers.isEnabled) {
   1654         //metadatabuffer mode
   1655         LOG_V("in metadata mode, data=%p, size=%d\n", inBuffer->data, inBuffer->size);
   1656         if (imb.UnSerialize(inBuffer->data, inBuffer->size) != IMB_SUCCESS) {
   1657             //fail to parse buffer
   1658             return ENCODE_NO_REQUEST_DATA;
   1659         }
   1660 
   1661         imb.GetType(type);
   1662         imb.GetValue(value);
   1663     } else {
   1664         //raw mode
   1665         LOG_I("in raw mode, data=%p, size=%d\n", inBuffer->data, inBuffer->size);
   1666         if (! inBuffer->data || inBuffer->size == 0) {
   1667             return ENCODE_NULL_PTR;
   1668         }
   1669 
   1670         type = IntelMetadataBufferTypeUser;
   1671         value = (intptr_t)inBuffer->data;
   1672     }
   1673 
   1674 #ifdef INTEL_VIDEO_XPROC_SHARING
   1675     uint32_t sflag = mSessionFlag;
   1676     imb.GetSessionFlag(mSessionFlag);
   1677     if (mSessionFlag != sflag) {
   1678         //new sharing session, flush buffer sharing cache
   1679         IntelMetadataBuffer::ClearContext(sflag, false);
   1680         //flush surfacemap cache
   1681         LOG_V( "Flush Src Surface Map\n");
   1682         while(! mSrcSurfaceMapList.empty())
   1683         {
   1684             delete (*mSrcSurfaceMapList.begin());
   1685             mSrcSurfaceMapList.erase(mSrcSurfaceMapList.begin());
   1686         }
   1687     }
   1688 #endif
   1689 
   1690     //find if mapped
   1691     map = (VASurfaceMap*) findSurfaceMapByValue(value);
   1692 
   1693     if (map) {
   1694         //has mapped, get surfaceID directly and do all necessary actions
   1695         LOG_V("direct find surface %d from value %i\n", map->getVASurface(), value);
   1696         *sid = map->getVASurface();
   1697         map->doMapping();
   1698         return ret;
   1699     }
   1700 
   1701     //if no found from list, then try to map value with parameters
   1702     LOG_V("not find surface from cache with value %i, start mapping if enough information\n", value);
   1703 
   1704     if (mStoreMetaDataInBuffers.isEnabled) {
   1705 
   1706         //if type is IntelMetadataBufferTypeGrallocSource, use default parameters since no ValueInfo
   1707         if (type == IntelMetadataBufferTypeGrallocSource) {
   1708             vinfo.mode = MEM_MODE_GFXHANDLE;
   1709             vinfo.handle = 0;
   1710             vinfo.size = 0;
   1711             vinfo.width = mComParams.resolution.width;
   1712             vinfo.height = mComParams.resolution.height;
   1713             vinfo.lumaStride = mComParams.resolution.width;
   1714             vinfo.chromStride = mComParams.resolution.width;
   1715             vinfo.format = VA_FOURCC_NV12;
   1716             vinfo.s3dformat = 0xFFFFFFFF;
   1717         } else {
   1718             //get all info mapping needs
   1719             imb.GetValueInfo(pvinfo);
   1720             imb.GetExtraValues(extravalues, extravalues_count);
   1721         }
   1722 
   1723     } else {
   1724 
   1725         //raw mode
   1726         vinfo.mode = MEM_MODE_MALLOC;
   1727         vinfo.handle = 0;
   1728         vinfo.size = inBuffer->size;
   1729         vinfo.width = mComParams.resolution.width;
   1730         vinfo.height = mComParams.resolution.height;
   1731         vinfo.lumaStride = mComParams.resolution.width;
   1732         vinfo.chromStride = mComParams.resolution.width;
   1733         vinfo.format = VA_FOURCC_NV12;
   1734         vinfo.s3dformat = 0xFFFFFFFF;
   1735     }
   1736 
   1737     /*  Start mapping, if pvinfo is not NULL, then have enough info to map;
   1738      *   if extravalues is not NULL, then need to do more times mapping
   1739      */
   1740     if (pvinfo){
   1741         //map according info, and add to surfacemap list
   1742         map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
   1743         map->setValue(value);
   1744         map->setValueInfo(*pvinfo);
   1745         map->setAction(mVASurfaceMappingAction);
   1746 
   1747         ret = map->doMapping();
   1748         if (ret == ENCODE_SUCCESS) {
   1749             LOG_V("surface mapping success, map value %i into surface %d\n", value, map->getVASurface());
   1750             mSrcSurfaceMapList.push_back(map);
   1751         } else {
   1752             delete map;
   1753             LOG_E("surface mapping failed, wrong info or meet serious error\n");
   1754             return ret;
   1755         }
   1756 
   1757         *sid = map->getVASurface();
   1758 
   1759     } else {
   1760         //can't map due to no info
   1761         LOG_E("surface mapping failed, missing information\n");
   1762         return ENCODE_NO_REQUEST_DATA;
   1763     }
   1764 
   1765     if (extravalues) {
   1766         //map more using same ValueInfo
   1767         for(unsigned int i=0; i<extravalues_count; i++) {
   1768             map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
   1769             map->setValue(extravalues[i]);
   1770             map->setValueInfo(vinfo);
   1771 
   1772             ret = map->doMapping();
   1773             if (ret == ENCODE_SUCCESS) {
   1774                 LOG_V("surface mapping extravalue success, map value %i into surface %d\n", extravalues[i], map->getVASurface());
   1775                 mSrcSurfaceMapList.push_back(map);
   1776             } else {
   1777                 delete map;
   1778                 map = NULL;
   1779                 LOG_E( "surface mapping extravalue failed, extravalue is %i\n", extravalues[i]);
   1780             }
   1781         }
   1782     }
   1783 
   1784     return ret;
   1785 }
   1786 
   1787 Encode_Status VideoEncoderBase::renderDynamicBitrate(EncodeTask* task) {
   1788     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1789 
   1790     LOG_V( "Begin\n\n");
   1791     // disable bits stuffing and skip frame apply to all rate control mode
   1792 
   1793     VAEncMiscParameterBuffer   *miscEncParamBuf;
   1794     VAEncMiscParameterRateControl *bitrateControlParam;
   1795     VABufferID miscParamBufferID;
   1796 
   1797     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
   1798             VAEncMiscParameterBufferType,
   1799             sizeof (VAEncMiscParameterBuffer) + sizeof (VAEncMiscParameterRateControl),
   1800             1, NULL,
   1801             &miscParamBufferID);
   1802 
   1803     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1804 
   1805     vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
   1806     CHECK_VA_STATUS_RETURN("vaMapBuffer");
   1807 
   1808     miscEncParamBuf->type = VAEncMiscParameterTypeRateControl;
   1809     bitrateControlParam = (VAEncMiscParameterRateControl *)miscEncParamBuf->data;
   1810 
   1811     bitrateControlParam->bits_per_second = mComParams.rcParams.bitRate;
   1812     bitrateControlParam->initial_qp = mComParams.rcParams.initQP;
   1813     if(mComParams.rcParams.enableIntraFrameQPControl && (task->type == FTYPE_IDR || task->type == FTYPE_I)) {
   1814         bitrateControlParam->min_qp = mComParams.rcParams.I_minQP;
   1815         bitrateControlParam->max_qp = mComParams.rcParams.I_maxQP;
   1816         mRenderBitRate = true;
   1817         LOG_I("apply I min/max qp for IDR or I frame\n");
   1818     } else {
   1819         bitrateControlParam->min_qp = mComParams.rcParams.minQP;
   1820         bitrateControlParam->max_qp = mComParams.rcParams.maxQP;
   1821         mRenderBitRate = false;
   1822         LOG_I("revert to original min/max qp after IDR or I frame\n");
   1823     }
   1824     bitrateControlParam->target_percentage = mComParams.rcParams.targetPercentage;
   1825     bitrateControlParam->window_size = mComParams.rcParams.windowSize;
   1826     bitrateControlParam->rc_flags.bits.disable_frame_skip = mComParams.rcParams.disableFrameSkip;
   1827     bitrateControlParam->rc_flags.bits.disable_bit_stuffing = mComParams.rcParams.disableBitsStuffing;
   1828     bitrateControlParam->basic_unit_size = 0;
   1829 
   1830     LOG_I("bits_per_second = %d\n", bitrateControlParam->bits_per_second);
   1831     LOG_I("initial_qp = %d\n", bitrateControlParam->initial_qp);
   1832     LOG_I("min_qp = %d\n", bitrateControlParam->min_qp);
   1833     LOG_I("max_qp = %d\n", bitrateControlParam->max_qp);
   1834     LOG_I("target_percentage = %d\n", bitrateControlParam->target_percentage);
   1835     LOG_I("window_size = %d\n", bitrateControlParam->window_size);
   1836     LOG_I("disable_frame_skip = %d\n", bitrateControlParam->rc_flags.bits.disable_frame_skip);
   1837     LOG_I("disable_bit_stuffing = %d\n", bitrateControlParam->rc_flags.bits.disable_bit_stuffing);
   1838 
   1839     vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
   1840     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
   1841 
   1842     vaStatus = vaRenderPicture(mVADisplay, mVAContext,
   1843             &miscParamBufferID, 1);
   1844     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1845 
   1846     return ENCODE_SUCCESS;
   1847 }
   1848 
   1849 
   1850 Encode_Status VideoEncoderBase::renderDynamicFrameRate() {
   1851 
   1852     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1853 
   1854     if (mComParams.rcMode != RATE_CONTROL_VCM) {
   1855 
   1856         LOG_W("Not in VCM mode, but call SendDynamicFramerate\n");
   1857         return ENCODE_SUCCESS;
   1858     }
   1859 
   1860     VAEncMiscParameterBuffer   *miscEncParamBuf;
   1861     VAEncMiscParameterFrameRate *frameRateParam;
   1862     VABufferID miscParamBufferID;
   1863 
   1864     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
   1865             VAEncMiscParameterBufferType,
   1866             sizeof(miscEncParamBuf) + sizeof(VAEncMiscParameterFrameRate),
   1867             1, NULL, &miscParamBufferID);
   1868     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1869 
   1870     vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
   1871     CHECK_VA_STATUS_RETURN("vaMapBuffer");
   1872 
   1873     miscEncParamBuf->type = VAEncMiscParameterTypeFrameRate;
   1874     frameRateParam = (VAEncMiscParameterFrameRate *)miscEncParamBuf->data;
   1875     frameRateParam->framerate =
   1876             (unsigned int) (mComParams.frameRate.frameRateNum + mComParams.frameRate.frameRateDenom/2)
   1877             / mComParams.frameRate.frameRateDenom;
   1878 
   1879     vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
   1880     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
   1881 
   1882     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
   1883     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1884 
   1885     LOG_I( "frame rate = %d\n", frameRateParam->framerate);
   1886     return ENCODE_SUCCESS;
   1887 }
   1888 
   1889 Encode_Status VideoEncoderBase::renderHrd() {
   1890 
   1891     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1892 
   1893     VAEncMiscParameterBuffer *miscEncParamBuf;
   1894     VAEncMiscParameterHRD *hrdParam;
   1895     VABufferID miscParamBufferID;
   1896 
   1897     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
   1898             VAEncMiscParameterBufferType,
   1899             sizeof(miscEncParamBuf) + sizeof(VAEncMiscParameterHRD),
   1900             1, NULL, &miscParamBufferID);
   1901     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1902 
   1903     vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
   1904     CHECK_VA_STATUS_RETURN("vaMapBuffer");
   1905 
   1906     miscEncParamBuf->type = VAEncMiscParameterTypeHRD;
   1907     hrdParam = (VAEncMiscParameterHRD *)miscEncParamBuf->data;
   1908 
   1909     hrdParam->buffer_size = mHrdParam.bufferSize;
   1910     hrdParam->initial_buffer_fullness = mHrdParam.initBufferFullness;
   1911 
   1912     vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
   1913     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
   1914 
   1915     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
   1916     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1917 
   1918     return ENCODE_SUCCESS;
   1919 }
   1920 
   1921 VASurfaceMap *VideoEncoderBase::findSurfaceMapByValue(intptr_t value) {
   1922     android::List<VASurfaceMap *>::iterator node;
   1923 
   1924     for(node = mSrcSurfaceMapList.begin(); node !=  mSrcSurfaceMapList.end(); node++)
   1925     {
   1926         if ((*node)->getValue() == value)
   1927             return *node;
   1928         else
   1929             continue;
   1930     }
   1931 
   1932     return NULL;
   1933 }
   1934