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 <stdlib.h>
     19 #include "VideoEncoderLog.h"
     20 #include "VideoEncoderAVC.h"
     21 #include <va/va_tpi.h>
     22 #include <va/va_enc_h264.h>
     23 #include <bitstream.h>
     24 
     25 VideoEncoderAVC::VideoEncoderAVC()
     26     :VideoEncoderBase() {
     27     if(VideoEncoderBase::queryProfileLevelConfig(mVADisplay, VAProfileH264High) == ENCODE_SUCCESS){
     28         mComParams.profile = VAProfileH264High;
     29         mComParams.level = 42;
     30     }else if(VideoEncoderBase::queryProfileLevelConfig(mVADisplay, VAProfileH264Main) == ENCODE_SUCCESS){
     31         mComParams.profile = VAProfileH264Main;
     32         mComParams.level = 41;
     33     }
     34     mVideoParamsAVC.basicUnitSize = 0;
     35     mVideoParamsAVC.VUIFlag = 0;
     36     mVideoParamsAVC.sliceNum.iSliceNum = 2;
     37     mVideoParamsAVC.sliceNum.pSliceNum = 2;
     38     mVideoParamsAVC.idrInterval = 2;
     39     mVideoParamsAVC.ipPeriod = 1;
     40     mVideoParamsAVC.maxSliceSize = 0;
     41     mVideoParamsAVC.delimiterType = AVC_DELIMITER_ANNEXB;
     42     mSliceNum = 2;
     43     mVideoParamsAVC.crop.LeftOffset = 0;
     44     mVideoParamsAVC.crop.RightOffset = 0;
     45     mVideoParamsAVC.crop.TopOffset = 0;
     46     mVideoParamsAVC.crop.BottomOffset = 0;
     47     mVideoParamsAVC.SAR.SarWidth = 0;
     48     mVideoParamsAVC.SAR.SarHeight = 0;
     49     mVideoParamsAVC.bEntropyCodingCABAC = 0;
     50     mVideoParamsAVC.bWeightedPPrediction = 0;
     51     mVideoParamsAVC.bDirect8x8Inference = 0;
     52     mVideoParamsAVC.bConstIpred = 0;
     53     mAutoReferenceSurfaceNum = 4;
     54 
     55     packed_seq_header_param_buf_id = VA_INVALID_ID;
     56     packed_seq_buf_id = VA_INVALID_ID;
     57     packed_pic_header_param_buf_id = VA_INVALID_ID;
     58     packed_pic_buf_id = VA_INVALID_ID;
     59     packed_sei_header_param_buf_id = VA_INVALID_ID;   /* the SEI buffer */
     60     packed_sei_buf_id = VA_INVALID_ID;
     61 }
     62 
     63 Encode_Status VideoEncoderAVC::start() {
     64 
     65     Encode_Status ret = ENCODE_SUCCESS;
     66     LOG_V( "Begin\n");
     67 
     68     if (mComParams.rcMode == VA_RC_VCM) {
     69         // If we are in VCM, we will set slice num to max value
     70         // mVideoParamsAVC.sliceNum.iSliceNum = (mComParams.resolution.height + 15) / 16;
     71         // mVideoParamsAVC.sliceNum.pSliceNum = mVideoParamsAVC.sliceNum.iSliceNum;
     72     }
     73 
     74     ret = VideoEncoderBase::start ();
     75     CHECK_ENCODE_STATUS_RETURN("VideoEncoderBase::start");
     76 
     77     LOG_V( "end\n");
     78     return ret;
     79 }
     80 
     81 Encode_Status VideoEncoderAVC::derivedSetParams(VideoParamConfigSet *videoEncParams) {
     82 
     83     CHECK_NULL_RETURN_IFFAIL(videoEncParams);
     84     VideoParamsAVC *encParamsAVC = reinterpret_cast <VideoParamsAVC *> (videoEncParams);
     85 
     86     // AVC parames
     87     if (encParamsAVC->size != sizeof (VideoParamsAVC)) {
     88         return ENCODE_INVALID_PARAMS;
     89     }
     90 
     91     if(encParamsAVC->ipPeriod == 0 || encParamsAVC->ipPeriod >4)
     92         return ENCODE_INVALID_PARAMS;
     93 
     94     if((mComParams.intraPeriod >1)&&(mComParams.intraPeriod % encParamsAVC->ipPeriod !=0))
     95         return ENCODE_INVALID_PARAMS;
     96 
     97     mVideoParamsAVC = *encParamsAVC;
     98     if(mComParams.profile == VAProfileH264Baseline){
     99         mVideoParamsAVC.bEntropyCodingCABAC = 0;
    100         mVideoParamsAVC.bDirect8x8Inference = 0;
    101         mVideoParamsAVC.bWeightedPPrediction = 0;
    102     }
    103     return ENCODE_SUCCESS;
    104 }
    105 
    106 Encode_Status VideoEncoderAVC:: derivedGetParams(VideoParamConfigSet *videoEncParams) {
    107 
    108     CHECK_NULL_RETURN_IFFAIL(videoEncParams);
    109     VideoParamsAVC *encParamsAVC = reinterpret_cast <VideoParamsAVC *> (videoEncParams);
    110 
    111     // AVC parames
    112     if (encParamsAVC->size != sizeof (VideoParamsAVC)) {
    113         return ENCODE_INVALID_PARAMS;
    114     }
    115 
    116     *encParamsAVC = mVideoParamsAVC;
    117     return ENCODE_SUCCESS;
    118 
    119 }
    120 
    121 Encode_Status VideoEncoderAVC::derivedSetConfig(VideoParamConfigSet *videoEncConfig) {
    122 
    123     CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
    124     LOG_V("Config type = %d\n", (int)videoEncConfig->type);
    125 
    126     switch (videoEncConfig->type) {
    127         case VideoConfigTypeAVCIntraPeriod: {
    128 
    129             VideoConfigAVCIntraPeriod *configAVCIntraPeriod =
    130                     reinterpret_cast <VideoConfigAVCIntraPeriod *> (videoEncConfig);
    131             // Config Intra Peroid
    132             if (configAVCIntraPeriod->size != sizeof (VideoConfigAVCIntraPeriod)) {
    133                 return ENCODE_INVALID_PARAMS;
    134             }
    135 
    136             if(configAVCIntraPeriod->ipPeriod == 0 || configAVCIntraPeriod->ipPeriod >4)
    137                 return ENCODE_INVALID_PARAMS;
    138             if((configAVCIntraPeriod->intraPeriod >1)&&(configAVCIntraPeriod->intraPeriod % configAVCIntraPeriod->ipPeriod !=0))
    139                 return ENCODE_INVALID_PARAMS;
    140 
    141             mVideoParamsAVC.idrInterval = configAVCIntraPeriod->idrInterval;
    142             mVideoParamsAVC.ipPeriod = configAVCIntraPeriod->ipPeriod;
    143             mComParams.intraPeriod = configAVCIntraPeriod->intraPeriod;
    144             mNewHeader = true;
    145             break;
    146         }
    147         case VideoConfigTypeNALSize: {
    148             // Config MTU
    149             VideoConfigNALSize *configNALSize =
    150                     reinterpret_cast <VideoConfigNALSize *> (videoEncConfig);
    151             if (configNALSize->size != sizeof (VideoConfigNALSize)) {
    152                 return ENCODE_INVALID_PARAMS;
    153             }
    154 
    155             mVideoParamsAVC.maxSliceSize = configNALSize->maxSliceSize;
    156             mRenderMaxSliceSize = true;
    157             break;
    158         }
    159         case VideoConfigTypeIDRRequest: {
    160             if(mVideoParamsAVC.ipPeriod >1)
    161                 return ENCODE_FAIL;
    162             else
    163                 mNewHeader = true;
    164             break;
    165         }
    166         case VideoConfigTypeSliceNum: {
    167 
    168             VideoConfigSliceNum *configSliceNum =
    169                     reinterpret_cast <VideoConfigSliceNum *> (videoEncConfig);
    170             // Config Slice size
    171             if (configSliceNum->size != sizeof (VideoConfigSliceNum)) {
    172                 return ENCODE_INVALID_PARAMS;
    173             }
    174 
    175             mVideoParamsAVC.sliceNum = configSliceNum->sliceNum;
    176             break;
    177         }
    178         default: {
    179             LOG_E ("Invalid Config Type");
    180             break;
    181         }
    182     }
    183 
    184     return ENCODE_SUCCESS;
    185 }
    186 
    187 Encode_Status VideoEncoderAVC:: derivedGetConfig(
    188         VideoParamConfigSet *videoEncConfig) {
    189 
    190     CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
    191     LOG_V("Config type = %d\n", (int)videoEncConfig->type);
    192 
    193     switch (videoEncConfig->type) {
    194 
    195         case VideoConfigTypeAVCIntraPeriod: {
    196 
    197             VideoConfigAVCIntraPeriod *configAVCIntraPeriod =
    198                     reinterpret_cast <VideoConfigAVCIntraPeriod *> (videoEncConfig);
    199             if (configAVCIntraPeriod->size != sizeof (VideoConfigAVCIntraPeriod)) {
    200                 return ENCODE_INVALID_PARAMS;
    201             }
    202 
    203             configAVCIntraPeriod->idrInterval = mVideoParamsAVC.idrInterval;
    204             configAVCIntraPeriod->intraPeriod = mComParams.intraPeriod;
    205             configAVCIntraPeriod->ipPeriod = mVideoParamsAVC.ipPeriod;
    206 
    207             break;
    208         }
    209         case VideoConfigTypeNALSize: {
    210 
    211             VideoConfigNALSize *configNALSize =
    212                     reinterpret_cast <VideoConfigNALSize *> (videoEncConfig);
    213             if (configNALSize->size != sizeof (VideoConfigNALSize)) {
    214                 return ENCODE_INVALID_PARAMS;
    215             }
    216 
    217             configNALSize->maxSliceSize = mVideoParamsAVC.maxSliceSize;
    218             break;
    219         }
    220         case VideoConfigTypeIDRRequest: {
    221             break;
    222 
    223         }
    224         case VideoConfigTypeSliceNum: {
    225 
    226             VideoConfigSliceNum *configSliceNum =
    227                     reinterpret_cast <VideoConfigSliceNum *> (videoEncConfig);
    228             if (configSliceNum->size != sizeof (VideoConfigSliceNum)) {
    229                 return ENCODE_INVALID_PARAMS;
    230             }
    231 
    232             configSliceNum->sliceNum = mVideoParamsAVC.sliceNum;
    233             break;
    234         }
    235         default: {
    236             LOG_E ("Invalid Config Type");
    237             break;
    238         }
    239     }
    240 
    241     return ENCODE_SUCCESS;
    242 }
    243 
    244 Encode_Status VideoEncoderAVC::updateFrameInfo(EncodeTask* task) {
    245     uint32_t idrPeroid = mComParams.intraPeriod * mVideoParamsAVC.idrInterval;
    246     FrameType frametype;
    247     uint32_t frame_num = mFrameNum;
    248     uint32_t intraPeriod = mComParams.intraPeriod;
    249 
    250     if (idrPeroid != 0) {
    251         if(mVideoParamsAVC.ipPeriod > 1)
    252             frame_num = frame_num % (idrPeroid + 1);
    253         else
    254             frame_num = frame_num % idrPeroid ;
    255     }else{
    256         if (mComParams.intraPeriod == 0)
    257             intraPeriod = 0xFFFFFFFF;
    258     }
    259 
    260 
    261     if(frame_num ==0){
    262         frametype = FTYPE_IDR;
    263     }else if(intraPeriod ==1)
    264         // only I frame need intraPeriod=idrInterval=ipPeriod=0
    265         frametype = FTYPE_I;
    266     else if(mVideoParamsAVC.ipPeriod == 1){ // no B frame
    267         if((frame_num >  1) &&((frame_num -1)%intraPeriod == 0))
    268             frametype = FTYPE_I;
    269         else
    270             frametype = FTYPE_P;
    271     } else {
    272         if(((frame_num-1)%intraPeriod == 0)&&(frame_num >intraPeriod))
    273             frametype = FTYPE_I;
    274         else{
    275             frame_num = frame_num%intraPeriod;
    276             if(frame_num == 0)
    277                 frametype = FTYPE_B;
    278             else if((frame_num-1)%mVideoParamsAVC.ipPeriod == 0)
    279                 frametype = FTYPE_P;
    280             else
    281                 frametype = FTYPE_B;
    282         }
    283     }
    284 
    285     if (frametype == FTYPE_IDR || frametype == FTYPE_I)
    286         task->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
    287 
    288     if (frametype != task->type) {
    289         const char* FrameTypeStr[10] = {"UNKNOWN", "I", "P", "B", "SI", "SP", "EI", "EP", "S", "IDR"};
    290         if ((uint32_t) task->type < 9)
    291             LOG_V("libMIX thinks it is %s Frame, the input is %s Frame", FrameTypeStr[frametype], FrameTypeStr[task->type]);
    292         else
    293             LOG_V("Wrong Frame type %d, type may not be initialized ?\n", task->type);
    294     }
    295 
    296 //temparily comment out to avoid uninitialize error
    297 //    if (task->type == FTYPE_UNKNOWN || (uint32_t) task->type > 9)
    298         task->type = frametype;
    299 
    300     return ENCODE_SUCCESS;
    301 }
    302 
    303 Encode_Status VideoEncoderAVC::getExtFormatOutput(VideoEncOutputBuffer *outBuffer) {
    304 
    305     Encode_Status ret = ENCODE_SUCCESS;
    306 
    307     LOG_V("Begin\n");
    308 
    309     switch (outBuffer->format) {
    310         case OUTPUT_CODEC_DATA: {
    311             // Output the codec data
    312             ret = outputCodecData(outBuffer);
    313             CHECK_ENCODE_STATUS_CLEANUP("outputCodecData");
    314             break;
    315         }
    316 
    317         case OUTPUT_ONE_NAL: {
    318             // Output only one NAL unit
    319             ret = outputOneNALU(outBuffer, true);
    320             CHECK_ENCODE_STATUS_CLEANUP("outputOneNALU");
    321             break;
    322         }
    323 
    324         case OUTPUT_ONE_NAL_WITHOUT_STARTCODE: {
    325             ret = outputOneNALU(outBuffer, false);
    326             CHECK_ENCODE_STATUS_CLEANUP("outputOneNALU");
    327             break;
    328         }
    329 
    330         case OUTPUT_LENGTH_PREFIXED: {
    331             // Output length prefixed
    332             ret = outputLengthPrefixed(outBuffer);
    333             CHECK_ENCODE_STATUS_CLEANUP("outputLengthPrefixed");
    334             break;
    335         }
    336 
    337         case OUTPUT_NALULENGTHS_PREFIXED: {
    338             // Output nalu lengths ahead of bitstream
    339             ret = outputNaluLengthsPrefixed(outBuffer);
    340             CHECK_ENCODE_STATUS_CLEANUP("outputNaluLengthsPrefixed");
    341             break;
    342         }
    343 
    344         default:
    345             LOG_E("Invalid buffer mode\n");
    346             ret = ENCODE_FAIL;
    347             break;
    348     }
    349 
    350     LOG_V("out size is = %d\n", outBuffer->dataSize);
    351 
    352 
    353 CLEAN_UP:
    354 
    355 
    356     LOG_V("End\n");
    357     return ret;
    358 }
    359 
    360 Encode_Status VideoEncoderAVC::getOneNALUnit(
    361         uint8_t *inBuffer, uint32_t bufSize, uint32_t *nalSize,
    362         uint32_t *nalType, uint32_t *nalOffset, uint32_t status) {
    363     uint32_t pos = 0;
    364     uint32_t zeroByteCount = 0;
    365     uint32_t singleByteTable[3][2] = {{1,0},{2,0},{2,3}};
    366     uint32_t dataRemaining = 0;
    367     uint8_t *dataPtr;
    368 
    369     // Don't need to check parameters here as we just checked by caller
    370     while ((inBuffer[pos++] == 0x00)) {
    371         zeroByteCount ++;
    372         if (pos >= bufSize)  //to make sure the buffer to be accessed is valid
    373             break;
    374     }
    375 
    376     if (inBuffer[pos - 1] != 0x01 || zeroByteCount < 2) {
    377         LOG_E("The stream is not AnnexB format \n");
    378         LOG_E("segment status is %x \n", status);
    379         return ENCODE_FAIL; //not AnnexB, we won't process it
    380     }
    381 
    382     *nalType = (*(inBuffer + pos)) & 0x1F;
    383     LOG_V ("NAL type = 0x%x\n", *nalType);
    384 
    385     zeroByteCount = 0;
    386     *nalOffset = pos;
    387 
    388     if (status & VA_CODED_BUF_STATUS_SINGLE_NALU) {
    389         *nalSize = bufSize - pos;
    390         return ENCODE_SUCCESS;
    391     }
    392 
    393     dataPtr  = inBuffer + pos;
    394     dataRemaining = bufSize - pos + 1;
    395 
    396     while ((dataRemaining > 0) && (zeroByteCount < 3)) {
    397         if (((((intptr_t)dataPtr) & 0xF ) == 0) && (0 == zeroByteCount)
    398                && (dataRemaining > 0xF)) {
    399 
    400             __asm__  (
    401                 //Data input
    402                 "movl %1, %%ecx\n\t"//data_ptr=>ecx
    403                 "movl %0, %%eax\n\t"//data_remaing=>eax
    404                 //Main compare loop
    405                 //
    406                 "0:\n\t"   //MATCH_8_ZERO:
    407                 "pxor %%xmm0,%%xmm0\n\t"//set 0=>xmm0
    408                 "pcmpeqb (%%ecx),%%xmm0\n\t"//data_ptr=xmm0,(byte==0)?0xFF:0x00
    409                 "pmovmskb %%xmm0, %%edx\n\t"//edx[0]=xmm0[7],edx[1]=xmm0[15],...,edx[15]=xmm0[127]
    410                 "test $0xAAAA, %%edx\n\t"//edx& 1010 1010 1010 1010b
    411                 "jnz 2f\n\t"//Not equal to zero means that at least one byte 0x00
    412 
    413                 "1:\n\t"  //PREPARE_NEXT_MATCH:
    414                 "sub $0x10, %%eax\n\t"//16 + ecx --> ecx
    415                 "add $0x10, %%ecx\n\t"//eax-16 --> eax
    416                 "cmp $0x10, %%eax\n\t"
    417                 "jge 0b\n\t"//search next 16 bytes
    418 
    419                 "2:\n\t"   //DATA_RET:
    420                 "movl %%ecx, %1\n\t"//output ecx->data_ptr
    421                 "movl %%eax, %0\n\t"//output eax->data_remaining
    422                 : "+m"(dataRemaining), "+m"(dataPtr)
    423                 :
    424                 :"eax", "ecx", "edx", "xmm0"
    425                 );
    426             if (0 >= dataRemaining) {
    427                 break;
    428             }
    429 
    430         }
    431         //check the value of each byte
    432         if ((*dataPtr) >= 2) {
    433 
    434             zeroByteCount = 0;
    435 
    436         }
    437         else {
    438             zeroByteCount = singleByteTable[zeroByteCount][*dataPtr];
    439          }
    440 
    441         dataPtr ++;
    442         dataRemaining --;
    443     }
    444 
    445     if ((3 == zeroByteCount) && (dataRemaining > 0)) {
    446 
    447         *nalSize =  bufSize - dataRemaining - *nalOffset - 3;
    448 
    449     } else if (0 == dataRemaining) {
    450 
    451         *nalSize = bufSize - *nalOffset;
    452     }
    453     return ENCODE_SUCCESS;
    454 }
    455 
    456 Encode_Status VideoEncoderAVC::getHeader(
    457         uint8_t *inBuffer, uint32_t bufSize, uint32_t *headerSize, uint32_t status) {
    458 
    459     uint32_t nalType = 0;
    460     uint32_t nalSize = 0;
    461     uint32_t nalOffset = 0;
    462     uint32_t size = 0;
    463     uint8_t *buf = inBuffer;
    464     Encode_Status ret = ENCODE_SUCCESS;
    465 
    466     *headerSize = 0;
    467     CHECK_NULL_RETURN_IFFAIL(inBuffer);
    468 
    469     if (bufSize == 0) {
    470         //bufSize shoule not be 0, error happens
    471         LOG_E("Buffer size is 0\n");
    472         return ENCODE_FAIL;
    473     }
    474 
    475     while (1) {
    476         nalType = nalSize = nalOffset = 0;
    477         ret = getOneNALUnit(buf, bufSize, &nalSize, &nalType, &nalOffset, status);
    478         CHECK_ENCODE_STATUS_RETURN("getOneNALUnit");
    479 
    480         LOG_V("NAL type = %d, NAL size = %d, offset = %d\n", nalType, nalSize, nalOffset);
    481         size = nalSize + nalOffset;
    482 
    483         // Codec_data should be SPS or PPS
    484         if (nalType == 7 || nalType == 8) {
    485             *headerSize += size;
    486             buf += size;
    487             bufSize -= size;
    488         } else {
    489             LOG_V("No header found or no header anymore\n");
    490             break;
    491         }
    492     }
    493 
    494     return ENCODE_SUCCESS;
    495 }
    496 
    497 Encode_Status VideoEncoderAVC::outputCodecData(
    498         VideoEncOutputBuffer *outBuffer) {
    499 
    500     Encode_Status ret = ENCODE_SUCCESS;
    501     uint32_t headerSize = 0;
    502 
    503     ret = getHeader((uint8_t *)mCurSegment->buf + mOffsetInSeg,
    504             mCurSegment->size - mOffsetInSeg, &headerSize, mCurSegment->status);
    505     CHECK_ENCODE_STATUS_RETURN("getHeader");
    506     if (headerSize == 0) {
    507         outBuffer->dataSize = 0;
    508         mCurSegment = NULL;
    509         return ENCODE_NO_REQUEST_DATA;
    510     }
    511 
    512     if (headerSize <= outBuffer->bufferSize) {
    513         memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg, headerSize);
    514         mTotalSizeCopied += headerSize;
    515         mOffsetInSeg += headerSize;
    516         outBuffer->dataSize = headerSize;
    517         outBuffer->remainingSize = 0;
    518         outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
    519         outBuffer->flag |= ENCODE_BUFFERFLAG_CODECCONFIG;
    520         outBuffer->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
    521     } else {
    522         // we need a big enough buffer, otherwise we won't output anything
    523         outBuffer->dataSize = 0;
    524         outBuffer->remainingSize = headerSize;
    525         outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID;
    526         LOG_E("Buffer size too small\n");
    527         return ENCODE_BUFFER_TOO_SMALL;
    528     }
    529 
    530     return ret;
    531 }
    532 
    533 Encode_Status VideoEncoderAVC::outputOneNALU(
    534         VideoEncOutputBuffer *outBuffer, bool startCode) {
    535 
    536     uint32_t nalType = 0;
    537     uint32_t nalSize = 0;
    538     uint32_t nalOffset = 0;
    539     uint32_t sizeToBeCopied = 0;
    540 
    541     Encode_Status ret = ENCODE_SUCCESS;
    542     CHECK_NULL_RETURN_IFFAIL(mCurSegment->buf);
    543 
    544     ret = getOneNALUnit((uint8_t *)mCurSegment->buf + mOffsetInSeg,
    545             mCurSegment->size - mOffsetInSeg, &nalSize, &nalType, &nalOffset, mCurSegment->status);
    546     CHECK_ENCODE_STATUS_RETURN("getOneNALUnit");
    547 
    548     // check if we need startcode along with the payload
    549     if (startCode) {
    550         sizeToBeCopied = nalSize + nalOffset;
    551     } else {
    552         sizeToBeCopied = nalSize;
    553     }
    554 
    555     if (sizeToBeCopied <= outBuffer->bufferSize) {
    556         if (startCode) {
    557             memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg, sizeToBeCopied);
    558         } else {
    559             memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg + nalOffset,
    560                    sizeToBeCopied);
    561         }
    562         mTotalSizeCopied += sizeToBeCopied;
    563         mOffsetInSeg += (nalSize + nalOffset);
    564         outBuffer->dataSize = sizeToBeCopied;
    565         outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
    566         outBuffer->remainingSize = 0;
    567     } else {
    568         // if nothing to be copied out, set flag to invalid
    569         outBuffer->dataSize = 0;
    570         outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID;
    571         outBuffer->remainingSize = sizeToBeCopied;
    572         LOG_W("Buffer size too small\n");
    573         return ENCODE_BUFFER_TOO_SMALL;
    574     }
    575 
    576     // check if all data in current segment has been copied out
    577     if (mCurSegment->size == mOffsetInSeg) {
    578         if (mCurSegment->next != NULL) {
    579             mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
    580             mOffsetInSeg = 0;
    581         } else {
    582             LOG_V("End of stream\n");
    583             outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
    584             mCurSegment = NULL;
    585         }
    586     }
    587 
    588     return ENCODE_SUCCESS;
    589 }
    590 
    591 Encode_Status VideoEncoderAVC::outputLengthPrefixed(VideoEncOutputBuffer *outBuffer) {
    592 
    593     Encode_Status ret = ENCODE_SUCCESS;
    594     uint32_t nalType = 0;
    595     uint32_t nalSize = 0;
    596     uint32_t nalOffset = 0;
    597     uint32_t sizeCopiedHere = 0;
    598 
    599     CHECK_NULL_RETURN_IFFAIL(mCurSegment->buf);
    600 
    601     while (1) {
    602 
    603         if (mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere) {
    604             LOG_E("mCurSegment->size < mOffsetInSeg  || outBuffer->bufferSize < sizeCopiedHere\n");
    605             return ENCODE_FAIL;
    606         }
    607 
    608         // we need to handle the whole bitstream NAL by NAL
    609         ret = getOneNALUnit(
    610                 (uint8_t *)mCurSegment->buf + mOffsetInSeg,
    611                 mCurSegment->size - mOffsetInSeg, &nalSize, &nalType, &nalOffset, mCurSegment->status);
    612         CHECK_ENCODE_STATUS_RETURN("getOneNALUnit");
    613 
    614         if (nalSize + 4 <= outBuffer->bufferSize - sizeCopiedHere) {
    615             // write the NAL length to bit stream
    616             outBuffer->data[sizeCopiedHere] = (nalSize >> 24) & 0xff;
    617             outBuffer->data[sizeCopiedHere + 1] = (nalSize >> 16) & 0xff;
    618             outBuffer->data[sizeCopiedHere + 2] = (nalSize >> 8)  & 0xff;
    619             outBuffer->data[sizeCopiedHere + 3] = nalSize   & 0xff;
    620 
    621             sizeCopiedHere += 4;
    622             mTotalSizeCopied += 4;
    623 
    624             memcpy(outBuffer->data + sizeCopiedHere,
    625                    (uint8_t *)mCurSegment->buf + mOffsetInSeg + nalOffset, nalSize);
    626 
    627             sizeCopiedHere += nalSize;
    628             mTotalSizeCopied += nalSize;
    629             mOffsetInSeg += (nalSize + nalOffset);
    630 
    631         } else {
    632             outBuffer->dataSize = sizeCopiedHere;
    633             // In case the start code is 3-byte length but we use 4-byte for length prefixed
    634             // so the remainingSize size may larger than the remaining data size
    635             outBuffer->remainingSize = mTotalSize - mTotalSizeCopied + 100;
    636             outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
    637             LOG_E("Buffer size too small\n");
    638             return ENCODE_BUFFER_TOO_SMALL;
    639         }
    640 
    641         // check if all data in current segment has been copied out
    642         if (mCurSegment->size == mOffsetInSeg) {
    643             if (mCurSegment->next != NULL) {
    644                 mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
    645                 mOffsetInSeg = 0;
    646             } else {
    647                 LOG_V("End of stream\n");
    648                 outBuffer->dataSize = sizeCopiedHere;
    649                 outBuffer->remainingSize = 0;
    650                 outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
    651                 mCurSegment = NULL;
    652                 break;
    653             }
    654         }
    655     }
    656 
    657     return ENCODE_SUCCESS;
    658 }
    659 
    660 Encode_Status VideoEncoderAVC::outputNaluLengthsPrefixed(VideoEncOutputBuffer *outBuffer) {
    661 
    662     Encode_Status ret = ENCODE_SUCCESS;
    663     uint32_t nalType = 0;
    664     uint32_t nalSize = 0;
    665     uint32_t nalOffset = 0;
    666     uint32_t sizeCopiedHere = 0;
    667     const uint32_t NALUINFO_OFFSET = 256;
    668     uint32_t nalNum = 0;
    669 
    670     CHECK_NULL_RETURN_IFFAIL(mCurSegment->buf);
    671 
    672     while (1) {
    673 
    674         if (mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere) {
    675             LOG_E("mCurSegment->size < mOffsetInSeg  || outBuffer->bufferSize < sizeCopiedHere\n");
    676             return ENCODE_FAIL;
    677         }
    678 
    679         // we need to handle the whole bitstream NAL by NAL
    680         ret = getOneNALUnit(
    681                 (uint8_t *)mCurSegment->buf + mOffsetInSeg,
    682                 mCurSegment->size - mOffsetInSeg, &nalSize, &nalType, &nalOffset, mCurSegment->status);
    683         CHECK_ENCODE_STATUS_RETURN("getOneNALUnit");
    684 
    685         if (nalSize + 4 <= outBuffer->bufferSize - NALUINFO_OFFSET - sizeCopiedHere) {
    686 
    687             memcpy(outBuffer->data + NALUINFO_OFFSET + sizeCopiedHere,
    688                    (uint8_t *)mCurSegment->buf + mOffsetInSeg, nalSize + nalOffset);
    689 
    690             sizeCopiedHere += nalSize + nalOffset;
    691             mTotalSizeCopied += nalSize + nalOffset;
    692             mOffsetInSeg += (nalSize + nalOffset);
    693 
    694         } else {
    695             outBuffer->dataSize = sizeCopiedHere;
    696             // In case the start code is 3-byte length but we use 4-byte for length prefixed
    697             // so the remainingSize size may larger than the remaining data size
    698             outBuffer->remainingSize = mTotalSize - mTotalSizeCopied + 100;
    699             outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
    700             LOG_E("Buffer size too small\n");
    701             return ENCODE_BUFFER_TOO_SMALL;
    702         }
    703 
    704         nalNum ++;
    705         uint32_t *nalLength = (uint32_t *) (outBuffer->data + (nalNum+1) * 4);
    706 
    707         *nalLength = nalSize + nalOffset;
    708 
    709         // check if all data in current segment has been copied out
    710         if (mCurSegment->size == mOffsetInSeg) {
    711             if (mCurSegment->next != NULL) {
    712                 mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
    713                 mOffsetInSeg = 0;
    714             } else {
    715                 LOG_V("End of stream\n");
    716                 outBuffer->dataSize = sizeCopiedHere;
    717                 outBuffer->remainingSize = 0;
    718                 outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
    719                 mCurSegment = NULL;
    720                 break;
    721             }
    722         }
    723     }
    724 
    725     outBuffer->offset = NALUINFO_OFFSET;
    726     uint32_t *nalHead = (uint32_t *) outBuffer->data;
    727     *nalHead = 0x4E414C4C; //'nall'
    728     *(++nalHead) = nalNum;
    729 
    730     return ENCODE_SUCCESS;
    731 }
    732 
    733 Encode_Status VideoEncoderAVC::sendEncodeCommand(EncodeTask *task) {
    734     Encode_Status ret = ENCODE_SUCCESS;
    735 
    736     LOG_V( "Begin\n");
    737 
    738     if (mFrameNum == 0 || mNewHeader) {
    739         if (mRenderHrd) {
    740             ret = renderHrd();
    741             mRenderHrd = false;
    742             CHECK_ENCODE_STATUS_RETURN("renderHrd");
    743         }
    744 
    745         mFrameNum = 0;
    746         ret = renderSequenceParams(task);
    747         CHECK_ENCODE_STATUS_RETURN("renderSequenceParams");
    748         if (mNewHeader) {
    749             mNewHeader = false; //Set to require new header filed to false
    750             mFrameNum = 0; //reset mFrameNum to 0
    751             updateFrameInfo(task); //recalculate frame info if mNewHeader is set true after PrepareFrameInfo in encode()
    752         }
    753     }
    754 
    755     if (mRenderMaxSliceSize && mVideoParamsAVC.maxSliceSize != 0) {
    756         ret = renderMaxSliceSize();
    757         CHECK_ENCODE_STATUS_RETURN("renderMaxSliceSize");
    758         mRenderMaxSliceSize = false;
    759     }
    760 
    761     if (mComParams.rcParams.enableIntraFrameQPControl && (task->type == FTYPE_IDR || task->type == FTYPE_I))
    762         mRenderBitRate = true;
    763 
    764     if (mRenderBitRate) {
    765         ret = VideoEncoderBase::renderDynamicBitrate(task);
    766         CHECK_ENCODE_STATUS_RETURN("renderDynamicBitrate");
    767     }
    768 
    769     if (mRenderAIR &&
    770         (mComParams.refreshType == VIDEO_ENC_AIR ||
    771         mComParams.refreshType == VIDEO_ENC_BOTH)) {
    772 
    773         ret = renderAIR();
    774         CHECK_ENCODE_STATUS_RETURN("renderAIR");
    775 
    776         mRenderAIR = false;
    777     }
    778 
    779     if (mRenderCIR) {
    780 
    781         ret = renderCIR();
    782         CHECK_ENCODE_STATUS_RETURN("renderCIR");
    783 
    784         mRenderCIR = false;
    785     }
    786 
    787     if (mRenderFrameRate) {
    788 
    789         ret = VideoEncoderBase::renderDynamicFrameRate();
    790         CHECK_ENCODE_STATUS_RETURN("renderDynamicFrameRate");
    791 
    792         mRenderFrameRate = false;
    793     }
    794 
    795     ret = renderPictureParams(task);
    796     CHECK_ENCODE_STATUS_RETURN("renderPictureParams");
    797 
    798     if (mFrameNum == 0 && (mEncPackedHeaders != VA_ATTRIB_NOT_SUPPORTED)) {
    799         ret = renderPackedSequenceParams(task);
    800         CHECK_ENCODE_STATUS_RETURN("renderPackedSequenceParams");
    801 
    802         ret = renderPackedPictureParams(task);
    803         CHECK_ENCODE_STATUS_RETURN("renderPackedPictureParams");
    804     }
    805 
    806     ret = renderSliceParams(task);
    807     CHECK_ENCODE_STATUS_RETURN("renderSliceParams");
    808 
    809     LOG_V( "End\n");
    810     return ENCODE_SUCCESS;
    811 }
    812 
    813 
    814 Encode_Status VideoEncoderAVC::renderMaxSliceSize() {
    815 
    816     VAStatus vaStatus = VA_STATUS_SUCCESS;
    817     LOG_V( "Begin\n\n");
    818 
    819     if (mComParams.rcMode != RATE_CONTROL_VCM) {
    820         LOG_W ("Not in VCM mode, but call send_max_slice_size\n");
    821         return ENCODE_SUCCESS;
    822     }
    823 
    824     VAEncMiscParameterBuffer *miscEncParamBuf;
    825     VAEncMiscParameterMaxSliceSize *maxSliceSizeParam;
    826     VABufferID miscParamBufferID;
    827 
    828     vaStatus = vaCreateBuffer(
    829             mVADisplay, mVAContext,
    830             VAEncMiscParameterBufferType,
    831             sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterMaxSliceSize),
    832             1, NULL, &miscParamBufferID);
    833     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
    834 
    835     vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
    836     CHECK_VA_STATUS_RETURN("vaMapBuffer");
    837 
    838     miscEncParamBuf->type = VAEncMiscParameterTypeMaxSliceSize;
    839     maxSliceSizeParam = (VAEncMiscParameterMaxSliceSize *)miscEncParamBuf->data;
    840 
    841     maxSliceSizeParam->max_slice_size = mVideoParamsAVC.maxSliceSize;
    842 
    843     vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
    844     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
    845 
    846     LOG_I( "max slice size = %d\n", maxSliceSizeParam->max_slice_size);
    847 
    848     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
    849     CHECK_VA_STATUS_RETURN("vaRenderPicture");
    850 
    851     return ENCODE_SUCCESS;
    852 }
    853 
    854 Encode_Status VideoEncoderAVC::renderCIR(){
    855     VAStatus vaStatus = VA_STATUS_SUCCESS;
    856     LOG_V( "%s Begin\n", __FUNCTION__);
    857 
    858     VABufferID miscParamBufferCIRid;
    859     VAEncMiscParameterBuffer *misc_param;
    860     VAEncMiscParameterCIR *misc_cir_param;
    861 
    862     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    863             VAEncMiscParameterBufferType,
    864             sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterCIR),
    865             1,
    866             NULL,
    867             &miscParamBufferCIRid);
    868     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
    869 
    870     vaStatus = vaMapBuffer(mVADisplay, miscParamBufferCIRid,  (void **)&misc_param);
    871     CHECK_VA_STATUS_RETURN("vaMapBuffer");
    872 
    873     misc_param->type = VAEncMiscParameterTypeCIR;
    874     misc_cir_param = (VAEncMiscParameterCIR *)misc_param->data;
    875     misc_cir_param->cir_num_mbs = mComParams.cirParams.cir_num_mbs;
    876     LOG_I( "cir_num_mbs %d \n", misc_cir_param->cir_num_mbs);
    877 
    878     vaUnmapBuffer(mVADisplay, miscParamBufferCIRid);
    879     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
    880 
    881     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferCIRid, 1);
    882     CHECK_VA_STATUS_RETURN("vaRenderPicture");
    883 
    884     return ENCODE_SUCCESS;
    885 }
    886 
    887 Encode_Status VideoEncoderAVC::renderAIR() {
    888     VAStatus vaStatus = VA_STATUS_SUCCESS;
    889     LOG_V( "Begin\n\n");
    890 
    891     VAEncMiscParameterBuffer   *miscEncParamBuf;
    892     VAEncMiscParameterAIR *airParams;
    893     VABufferID miscParamBufferID;
    894 
    895     vaStatus = vaCreateBuffer(
    896             mVADisplay, mVAContext,
    897             VAEncMiscParameterBufferType,
    898             sizeof(miscEncParamBuf) + sizeof(VAEncMiscParameterAIR),
    899             1, NULL, &miscParamBufferID);
    900     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
    901 
    902     vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
    903     CHECK_VA_STATUS_RETURN("vaMapBuffer");
    904 
    905     miscEncParamBuf->type = VAEncMiscParameterTypeAIR;
    906     airParams = (VAEncMiscParameterAIR *)miscEncParamBuf->data;
    907 
    908     airParams->air_num_mbs = mComParams.airParams.airMBs;
    909     airParams->air_threshold= mComParams.airParams.airThreshold;
    910     airParams->air_auto = mComParams.airParams.airAuto;
    911 
    912     vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
    913     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
    914 
    915     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
    916     CHECK_VA_STATUS_RETURN("vaRenderPicture");
    917 
    918     LOG_I( "airThreshold = %d\n", airParams->air_threshold);
    919     return ENCODE_SUCCESS;
    920 }
    921 
    922 int VideoEncoderAVC::calcLevel(int numMbs) {
    923     int level = 30;
    924 
    925     if (numMbs < 1620) {
    926         level = 30;
    927     } else if (numMbs < 3600) {
    928         level = 31;
    929     } else if (numMbs < 5120) {
    930         level = 32;
    931     } else if (numMbs < 8192) {
    932         level = 41;
    933     } else if (numMbs < 8704) {
    934         level = 42;
    935     } else if (numMbs < 22080) {
    936         level = 50;
    937     } else if (numMbs < 36864) {
    938         level = 51;
    939     } else {
    940         LOG_W("No such level can support that resolution");
    941         level = 51;
    942     }
    943     return level;
    944 }
    945 
    946 Encode_Status VideoEncoderAVC::renderSequenceParams(EncodeTask *) {
    947 
    948     VAStatus vaStatus = VA_STATUS_SUCCESS;
    949     VAEncSequenceParameterBufferH264 avcSeqParams = VAEncSequenceParameterBufferH264();
    950     VAEncMiscParameterBuffer   *miscEncRCParamBuf;
    951     VAEncMiscParameterBuffer   *miscEncFrameRateParamBuf;
    952     VAEncMiscParameterRateControl *rcMiscParam;
    953     VAEncMiscParameterFrameRate *framerateParam;
    954     int level;
    955     uint32_t frameRateNum = mComParams.frameRate.frameRateNum;
    956     uint32_t frameRateDenom = mComParams.frameRate.frameRateDenom;
    957 
    958     LOG_V( "Begin\n\n");
    959     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    960             VAEncMiscParameterBufferType,
    961             sizeof (VAEncMiscParameterBuffer) + sizeof (VAEncMiscParameterRateControl),
    962             1, NULL,
    963             &mRcParamBuf);
    964     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
    965     vaStatus = vaMapBuffer(mVADisplay, mRcParamBuf, (void **)&miscEncRCParamBuf);
    966     CHECK_VA_STATUS_RETURN("vaMapBuffer");
    967 
    968     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
    969             VAEncMiscParameterBufferType,
    970             sizeof (VAEncMiscParameterBuffer) + sizeof (VAEncMiscParameterFrameRate),
    971             1, NULL,
    972             &mFrameRateParamBuf);
    973     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
    974     vaStatus = vaMapBuffer(mVADisplay, mFrameRateParamBuf, (void **)&miscEncFrameRateParamBuf);
    975     CHECK_VA_STATUS_RETURN("vaMapBuffer");
    976 
    977     miscEncRCParamBuf->type = VAEncMiscParameterTypeRateControl;
    978     rcMiscParam = (VAEncMiscParameterRateControl  *)miscEncRCParamBuf->data;
    979     miscEncFrameRateParamBuf->type = VAEncMiscParameterTypeFrameRate;
    980     framerateParam = (VAEncMiscParameterFrameRate *)miscEncFrameRateParamBuf->data;
    981     // set up the sequence params for HW
    982     // avcSeqParams.level_idc = mLevel;
    983     avcSeqParams.intra_period = mComParams.intraPeriod;
    984     avcSeqParams.intra_idr_period = mVideoParamsAVC.idrInterval;
    985     avcSeqParams.ip_period = mVideoParamsAVC.ipPeriod;
    986     avcSeqParams.picture_width_in_mbs = (mComParams.resolution.width + 15) / 16;
    987     avcSeqParams.picture_height_in_mbs = (mComParams.resolution.height + 15) / 16;
    988 
    989     level = calcLevel (avcSeqParams.picture_width_in_mbs * avcSeqParams.picture_height_in_mbs);
    990     avcSeqParams.level_idc = level;
    991     avcSeqParams.bits_per_second = mComParams.rcParams.bitRate;
    992     framerateParam->framerate =
    993             (unsigned int) (frameRateNum + frameRateDenom /2 ) / frameRateDenom;
    994     rcMiscParam->initial_qp = mComParams.rcParams.initQP;
    995     rcMiscParam->min_qp = mComParams.rcParams.minQP;
    996     rcMiscParam->max_qp = mComParams.rcParams.maxQP;
    997     if (mComParams.rcParams.enableIntraFrameQPControl) {
    998         rcMiscParam->min_qp = mComParams.rcParams.I_minQP;
    999         rcMiscParam->max_qp = mComParams.rcParams.I_maxQP;
   1000     }
   1001     rcMiscParam->window_size = mComParams.rcParams.windowSize;
   1002     //target bitrate is sent to libva through Sequence Parameter Buffer
   1003     rcMiscParam->bits_per_second = 0;
   1004     rcMiscParam->basic_unit_size = mVideoParamsAVC.basicUnitSize; //for rate control usage
   1005     avcSeqParams.intra_period = mComParams.intraPeriod;
   1006     //avcSeqParams.vui_flag = 248;
   1007     avcSeqParams.vui_parameters_present_flag = mVideoParamsAVC.VUIFlag;
   1008     avcSeqParams.num_units_in_tick = frameRateDenom;
   1009     avcSeqParams.time_scale = 2 * frameRateNum;
   1010     avcSeqParams.seq_parameter_set_id = 0;
   1011     if (mVideoParamsAVC.crop.LeftOffset ||
   1012             mVideoParamsAVC.crop.RightOffset ||
   1013             mVideoParamsAVC.crop.TopOffset ||
   1014             mVideoParamsAVC.crop.BottomOffset) {
   1015         avcSeqParams.frame_cropping_flag = true;
   1016         avcSeqParams.frame_crop_left_offset = mVideoParamsAVC.crop.LeftOffset;
   1017         avcSeqParams.frame_crop_right_offset = mVideoParamsAVC.crop.RightOffset;
   1018         avcSeqParams.frame_crop_top_offset = mVideoParamsAVC.crop.TopOffset;
   1019         avcSeqParams.frame_crop_bottom_offset = mVideoParamsAVC.crop.BottomOffset;
   1020     } else {
   1021         avcSeqParams.frame_cropping_flag = false;
   1022 
   1023         if (mComParams.resolution.width & 0xf) {
   1024             avcSeqParams.frame_cropping_flag = true;
   1025             uint32_t AWidth = (mComParams.resolution.width + 0xf) & (~0xf);
   1026             avcSeqParams.frame_crop_right_offset = ( AWidth - mComParams.resolution.width ) / 2;
   1027         }
   1028 
   1029         if (mComParams.resolution.height & 0xf) {
   1030             avcSeqParams.frame_cropping_flag = true;
   1031             uint32_t AHeight = (mComParams.resolution.height + 0xf) & (~0xf);
   1032             avcSeqParams.frame_crop_bottom_offset = ( AHeight - mComParams.resolution.height ) / 2;
   1033         }
   1034     }
   1035 
   1036     if(avcSeqParams.vui_parameters_present_flag && (mVideoParamsAVC.SAR.SarWidth || mVideoParamsAVC.SAR.SarHeight)) {
   1037         avcSeqParams.vui_fields.bits.aspect_ratio_info_present_flag = true;
   1038         avcSeqParams.aspect_ratio_idc = 0xff /* Extended_SAR */;
   1039         avcSeqParams.sar_width = mVideoParamsAVC.SAR.SarWidth;
   1040         avcSeqParams.sar_height = mVideoParamsAVC.SAR.SarHeight;
   1041     }
   1042 
   1043     avcSeqParams.max_num_ref_frames = 1;
   1044 
   1045     if(avcSeqParams.ip_period > 1)
   1046         avcSeqParams.max_num_ref_frames = 2;
   1047 
   1048     LOG_V("===h264 sequence params===\n");
   1049     LOG_V( "seq_parameter_set_id = %d\n", (uint32_t)avcSeqParams.seq_parameter_set_id);
   1050     LOG_V( "level_idc = %d\n", (uint32_t)avcSeqParams.level_idc);
   1051     LOG_V( "intra_period = %d\n", avcSeqParams.intra_period);
   1052     LOG_V( "idr_interval = %d\n", avcSeqParams.intra_idr_period);
   1053     LOG_V( "picture_width_in_mbs = %d\n", avcSeqParams.picture_width_in_mbs);
   1054     LOG_V( "picture_height_in_mbs = %d\n", avcSeqParams.picture_height_in_mbs);
   1055     LOG_V( "bitrate = %d\n", rcMiscParam->bits_per_second);
   1056     LOG_V( "frame_rate = %d\n", framerateParam->framerate);
   1057     LOG_V( "initial_qp = %d\n", rcMiscParam->initial_qp);
   1058     LOG_V( "min_qp = %d\n", rcMiscParam->min_qp);
   1059     LOG_V( "basic_unit_size = %d\n", rcMiscParam->basic_unit_size);
   1060     LOG_V( "bDirect8x8Inference = %d\n",mVideoParamsAVC.bDirect8x8Inference);
   1061 
   1062     // Not sure whether these settings work for all drivers
   1063     avcSeqParams.seq_fields.bits.frame_mbs_only_flag = 1;
   1064     avcSeqParams.seq_fields.bits.pic_order_cnt_type = 0;
   1065     avcSeqParams.seq_fields.bits.direct_8x8_inference_flag = mVideoParamsAVC.bDirect8x8Inference;
   1066 
   1067     avcSeqParams.seq_fields.bits.log2_max_frame_num_minus4 = 0;
   1068     avcSeqParams.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = 2;
   1069 //    avcSeqParams.time_scale = 900;
   1070 //    avcSeqParams.num_units_in_tick = 15;			/* Tc = num_units_in_tick / time_sacle */
   1071     // Not sure whether these settings work for all drivers
   1072 
   1073     vaStatus = vaUnmapBuffer(mVADisplay, mRcParamBuf);
   1074     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
   1075     vaStatus = vaUnmapBuffer(mVADisplay, mFrameRateParamBuf);
   1076     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
   1077     vaStatus = vaCreateBuffer(
   1078             mVADisplay, mVAContext,
   1079             VAEncSequenceParameterBufferType,
   1080             sizeof(avcSeqParams), 1, &avcSeqParams,
   1081             &mSeqParamBuf);
   1082     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1083     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mFrameRateParamBuf, 1);
   1084     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1085     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSeqParamBuf, 1);
   1086     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1087     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mRcParamBuf, 1);
   1088     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1089 
   1090     return ENCODE_SUCCESS;
   1091 }
   1092 
   1093 Encode_Status VideoEncoderAVC::renderPackedSequenceParams(EncodeTask *) {
   1094 
   1095     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1096     VAEncSequenceParameterBufferH264 *avcSeqParams;
   1097     VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
   1098     unsigned char *packed_seq_buffer = NULL;
   1099     unsigned int length_in_bits;
   1100 
   1101     LOG_V("Begin\n");
   1102 
   1103     vaStatus = vaMapBuffer(mVADisplay, mSeqParamBuf, (void **)&avcSeqParams);
   1104     CHECK_VA_STATUS_RETURN("vaMapBuffer");
   1105 
   1106     length_in_bits = build_packed_seq_buffer(&packed_seq_buffer, mComParams.profile, avcSeqParams);
   1107     packed_header_param_buffer.type = VAEncPackedHeaderSequence;
   1108     packed_header_param_buffer.bit_length = length_in_bits;
   1109     packed_header_param_buffer.has_emulation_bytes = 0;
   1110     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
   1111             VAEncPackedHeaderParameterBufferType,
   1112             sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
   1113             &packed_seq_header_param_buf_id);
   1114     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1115 
   1116     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
   1117             VAEncPackedHeaderDataBufferType,
   1118             (length_in_bits + 7) / 8, 1, packed_seq_buffer,
   1119             &packed_seq_buf_id);
   1120     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1121 
   1122     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &packed_seq_header_param_buf_id, 1);
   1123     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1124 
   1125     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &packed_seq_buf_id, 1);
   1126     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1127 
   1128     vaStatus = vaUnmapBuffer(mVADisplay, mSeqParamBuf);
   1129     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
   1130 
   1131     free(packed_seq_buffer);
   1132 
   1133     LOG_V("End\n");
   1134 
   1135     return vaStatus;
   1136 }
   1137 
   1138 Encode_Status VideoEncoderAVC::renderPictureParams(EncodeTask *task) {
   1139 
   1140     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1141     VAEncPictureParameterBufferH264 avcPicParams = VAEncPictureParameterBufferH264();
   1142     uint32_t RefFrmIdx;
   1143 
   1144     LOG_V( "Begin\n\n");
   1145     // set picture params for HW
   1146     if (mAutoReference == false) {
   1147         for (RefFrmIdx = 0; RefFrmIdx < 16; RefFrmIdx++) {
   1148             avcPicParams.ReferenceFrames[RefFrmIdx].picture_id = VA_INVALID_ID;
   1149             avcPicParams.ReferenceFrames[RefFrmIdx].flags = VA_PICTURE_H264_INVALID;
   1150         }
   1151         avcPicParams.ReferenceFrames[0].picture_id= task->ref_surface;
   1152         avcPicParams.ReferenceFrames[0].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
   1153         avcPicParams.CurrPic.picture_id= task->rec_surface;
   1154         // Not sure whether these settings work for all drivers
   1155         avcPicParams.CurrPic.TopFieldOrderCnt = mFrameNum * 2;
   1156 
   1157         avcPicParams.pic_fields.bits.transform_8x8_mode_flag = 0;
   1158         avcPicParams.seq_parameter_set_id = 0;
   1159         avcPicParams.pic_parameter_set_id = 0;
   1160 
   1161         avcPicParams.last_picture = 0;
   1162         avcPicParams.frame_num = 0;
   1163 
   1164         avcPicParams.pic_init_qp = 26;
   1165         avcPicParams.num_ref_idx_l0_active_minus1 = 0;
   1166         avcPicParams.num_ref_idx_l1_active_minus1 = 0;
   1167 
   1168         avcPicParams.pic_fields.bits.idr_pic_flag = 0;
   1169         avcPicParams.pic_fields.bits.reference_pic_flag = 0;
   1170         avcPicParams.pic_fields.bits.entropy_coding_mode_flag = 0;
   1171         avcPicParams.pic_fields.bits.weighted_pred_flag = 0;
   1172         avcPicParams.pic_fields.bits.weighted_bipred_idc = 0;
   1173         avcPicParams.pic_fields.bits.transform_8x8_mode_flag = 0;
   1174         avcPicParams.pic_fields.bits.deblocking_filter_control_present_flag = 1;
   1175 
   1176         avcPicParams.frame_num = mFrameNum;
   1177         avcPicParams.pic_fields.bits.reference_pic_flag = 1;
   1178         // Not sure whether these settings work for all drivers
   1179     }else {
   1180         avcPicParams.CurrPic.picture_id= VA_INVALID_SURFACE;
   1181         for(uint32_t i =0; i< mAutoReferenceSurfaceNum; i++)
   1182             avcPicParams.ReferenceFrames[i].picture_id = mAutoRefSurfaces[i];
   1183     }
   1184 
   1185     avcPicParams.pic_fields.bits.idr_pic_flag = (mFrameNum == 0);
   1186     avcPicParams.pic_fields.bits.entropy_coding_mode_flag = mVideoParamsAVC.bEntropyCodingCABAC;
   1187     avcPicParams.coded_buf = task->coded_buffer;
   1188     avcPicParams.last_picture = 0;
   1189 
   1190     LOG_V("======h264 picture params======\n");
   1191     LOG_V( "reference_picture = 0x%08x\n", avcPicParams.ReferenceFrames[0].picture_id);
   1192     LOG_V( "reconstructed_picture = 0x%08x\n", avcPicParams.CurrPic.picture_id);
   1193     LOG_V( "coded_buf = 0x%08x\n", avcPicParams.coded_buf);
   1194     //LOG_I( "picture_width = %d\n", avcPicParams.picture_width);
   1195     //LOG_I( "picture_height = %d\n\n", avcPicParams.picture_height);
   1196 
   1197     vaStatus = vaCreateBuffer(
   1198             mVADisplay, mVAContext,
   1199             VAEncPictureParameterBufferType,
   1200             sizeof(avcPicParams),
   1201             1,&avcPicParams,
   1202             &mPicParamBuf);
   1203     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1204 
   1205     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mPicParamBuf, 1);
   1206     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1207 
   1208     LOG_V( "end\n");
   1209     return ENCODE_SUCCESS;
   1210 }
   1211 
   1212 Encode_Status VideoEncoderAVC::renderPackedPictureParams(EncodeTask *) {
   1213 
   1214     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1215     VAEncPictureParameterBufferH264 *avcPicParams;
   1216     VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
   1217     unsigned char *packed_pic_buffer = NULL;
   1218     unsigned int length_in_bits;
   1219 
   1220     LOG_V("Begin\n");
   1221 
   1222     vaStatus = vaMapBuffer(mVADisplay, mPicParamBuf, (void **)&avcPicParams);
   1223     CHECK_VA_STATUS_RETURN("vaMapBuffer");
   1224 
   1225     length_in_bits = build_packed_pic_buffer(&packed_pic_buffer, avcPicParams);
   1226     packed_header_param_buffer.type = VAEncPackedHeaderPicture;
   1227     packed_header_param_buffer.bit_length = length_in_bits;
   1228     packed_header_param_buffer.has_emulation_bytes = 0;
   1229     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
   1230             VAEncPackedHeaderParameterBufferType,
   1231             sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
   1232             &packed_pic_header_param_buf_id);
   1233     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1234 
   1235     vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
   1236             VAEncPackedHeaderDataBufferType,
   1237             (length_in_bits + 7) / 8, 1, packed_pic_buffer,
   1238             &packed_pic_buf_id);
   1239     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1240 
   1241     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &packed_pic_header_param_buf_id, 1);
   1242     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1243 
   1244     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &packed_pic_buf_id, 1);
   1245     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1246 
   1247     vaStatus = vaUnmapBuffer(mVADisplay, mSeqParamBuf);
   1248     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
   1249 
   1250     free(packed_pic_buffer);
   1251 
   1252     LOG_V("End\n");
   1253 
   1254     return vaStatus;
   1255 }
   1256 
   1257 Encode_Status VideoEncoderAVC::renderSliceParams(EncodeTask *task) {
   1258 
   1259     VAStatus vaStatus = VA_STATUS_SUCCESS;
   1260 
   1261     uint32_t sliceNum = 0;
   1262     uint32_t sliceIndex = 0;
   1263     uint32_t sliceHeightInMB = 0;
   1264     uint32_t maxSliceNum = 0;
   1265     uint32_t minSliceNum = 0;
   1266     uint32_t actualSliceHeightInMB = 0;
   1267     uint32_t startRowInMB = 0;
   1268     uint32_t modulus = 0;
   1269     uint32_t RefFrmIdx;
   1270 
   1271     LOG_V( "Begin\n\n");
   1272 
   1273     maxSliceNum = (mComParams.resolution.height + 15) / 16;
   1274     minSliceNum = 1;
   1275 
   1276     if (task->type == FTYPE_I || task->type == FTYPE_IDR) {
   1277         sliceNum = mVideoParamsAVC.sliceNum.iSliceNum;
   1278     } else {
   1279         sliceNum = mVideoParamsAVC.sliceNum.pSliceNum;
   1280     }
   1281 
   1282     if (sliceNum < minSliceNum) {
   1283         LOG_W("Slice Number is too small");
   1284         sliceNum = minSliceNum;
   1285     }
   1286 
   1287     if (sliceNum > maxSliceNum) {
   1288         LOG_W("Slice Number is too big");
   1289         sliceNum = maxSliceNum;
   1290     }
   1291 
   1292     mSliceNum= sliceNum;
   1293     modulus = maxSliceNum % sliceNum;
   1294     sliceHeightInMB = (maxSliceNum - modulus) / sliceNum ;
   1295 
   1296     vaStatus = vaCreateBuffer(
   1297             mVADisplay, mVAContext,
   1298             VAEncSliceParameterBufferType,
   1299             sizeof(VAEncSliceParameterBufferH264),
   1300             sliceNum, NULL,
   1301             &mSliceParamBuf);
   1302     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
   1303 
   1304     VAEncSliceParameterBufferH264 *sliceParams, *currentSlice;
   1305 
   1306     vaStatus = vaMapBuffer(mVADisplay, mSliceParamBuf, (void **)&sliceParams);
   1307     CHECK_VA_STATUS_RETURN("vaMapBuffer");
   1308     if(!sliceParams)
   1309         return ENCODE_NULL_PTR;
   1310     memset(sliceParams, 0 , sizeof(VAEncSliceParameterBufferH264));
   1311     if(!sliceParams)
   1312         return ENCODE_NULL_PTR;
   1313 
   1314     currentSlice = sliceParams;
   1315     startRowInMB = 0;
   1316     for (sliceIndex = 0; sliceIndex < sliceNum; sliceIndex++) {
   1317         currentSlice = sliceParams + sliceIndex;
   1318         actualSliceHeightInMB = sliceHeightInMB;
   1319         if (sliceIndex < modulus) {
   1320             actualSliceHeightInMB ++;
   1321         }
   1322 
   1323         // starting MB row number for this slice, suppose macroblock 16x16
   1324         currentSlice->macroblock_address = startRowInMB * ((mComParams.resolution.width + 0xf) & ~0xf) / 16;
   1325         // slice height measured in MB
   1326         currentSlice->num_macroblocks = actualSliceHeightInMB * ((mComParams.resolution.width + 0xf) & ~0xf) / 16;
   1327         if(task->type == FTYPE_I||task->type == FTYPE_IDR)
   1328             currentSlice->slice_type = 2;
   1329         else if(task->type == FTYPE_P)
   1330             currentSlice->slice_type = 0;
   1331         else if(task->type == FTYPE_B)
   1332             currentSlice->slice_type = 1;
   1333         currentSlice->disable_deblocking_filter_idc = mComParams.disableDeblocking;
   1334 
   1335         // This is a temporary fix suggested by Binglin for bad encoding quality issue
   1336         // TODO: We need a long term design for this field
   1337         //currentSlice->slice_flags.bits.uses_long_term_ref = 0;
   1338         //currentSlice->slice_flags.bits.is_long_term_ref = 0;
   1339 
   1340         LOG_V("======AVC slice params======\n");
   1341         LOG_V( "slice_index = %d\n", (int) sliceIndex);
   1342         LOG_V( "macroblock_address = %d\n", (int) currentSlice->macroblock_address);
   1343         LOG_V( "slice_height_in_mb = %d\n", (int) currentSlice->num_macroblocks);
   1344         LOG_V( "slice.type = %d\n", (int) currentSlice->slice_type);
   1345         LOG_V("disable_deblocking_filter_idc = %d\n\n", (int) currentSlice->disable_deblocking_filter_idc);
   1346 
   1347         // Not sure whether these settings work for all drivers
   1348         currentSlice->pic_parameter_set_id = 0;
   1349         currentSlice->pic_order_cnt_lsb = mFrameNum * 2;
   1350         currentSlice->direct_spatial_mv_pred_flag = 0;
   1351         currentSlice->num_ref_idx_l0_active_minus1 = 0;      /* FIXME: ??? */
   1352         currentSlice->num_ref_idx_l1_active_minus1 = 0;
   1353         currentSlice->cabac_init_idc = 0;
   1354         currentSlice->slice_qp_delta = 0;
   1355         currentSlice->disable_deblocking_filter_idc = 0;
   1356         currentSlice->slice_alpha_c0_offset_div2 = 2;
   1357         currentSlice->slice_beta_offset_div2 = 2;
   1358         currentSlice->idr_pic_id = 0;
   1359         for (RefFrmIdx = 0; RefFrmIdx < 32; RefFrmIdx++) {
   1360             currentSlice->RefPicList0[RefFrmIdx].picture_id = VA_INVALID_ID;
   1361             currentSlice->RefPicList0[RefFrmIdx].flags = VA_PICTURE_H264_INVALID;
   1362         }
   1363         currentSlice->RefPicList0[0].picture_id = task->ref_surface;
   1364         currentSlice->RefPicList0[0].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
   1365         // Not sure whether these settings work for all drivers
   1366 
   1367         startRowInMB += actualSliceHeightInMB;
   1368     }
   1369 
   1370     vaStatus = vaUnmapBuffer(mVADisplay, mSliceParamBuf);
   1371     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
   1372 
   1373     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSliceParamBuf, 1);
   1374     CHECK_VA_STATUS_RETURN("vaRenderPicture");
   1375     LOG_V( "end\n");
   1376     return ENCODE_SUCCESS;
   1377 }
   1378