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