VideoEncoderBase.cpp revision e1569e56a264e55206110ff8010b6ccfab41e090
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
27VideoEncoderBase::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
94VideoEncoderBase::~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
113Encode_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
324Encode_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
440CLEAN_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*/
461Encode_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
573CLEAN_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
598void VideoEncoderBase::flush() {
599
600    LOG_V( "Begin\n");
601
602    // reset the properities
603    mFrameNum = 0;
604
605    LOG_V( "end\n");
606}
607
608Encode_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
661CLEAN_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
678Encode_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
778Encode_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
803Encode_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
823Encode_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
841Encode_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
875Encode_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
926void 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
969Encode_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
1076Encode_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
1201Encode_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
1320Encode_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
1417void VideoEncoderBase:: PrepareFrameInfo (EncodeTask* task) {
1418    if (mNewHeader) mFrameNum = 0;
1419    LOG_V( "mFrameNum = %d   ", mFrameNum);
1420
1421    updateFrameInfo(task) ;
1422}
1423
1424Encode_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
1440Encode_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
1492Encode_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
1595Encode_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
1639Encode_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
1787Encode_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
1850Encode_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
1889Encode_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
1921VASurfaceMap *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