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 
VideoEncoderAVC()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 
start()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 
derivedSetParams(VideoParamConfigSet * videoEncParams)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 
derivedGetParams(VideoParamConfigSet * videoEncParams)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 
derivedSetConfig(VideoParamConfigSet * videoEncConfig)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 
derivedGetConfig(VideoParamConfigSet * videoEncConfig)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 
updateFrameInfo(EncodeTask * task)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 
getExtFormatOutput(VideoEncOutputBuffer * outBuffer)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 
getOneNALUnit(uint8_t * inBuffer,uint32_t bufSize,uint32_t * nalSize,uint32_t * nalType,uint32_t * nalOffset,uint32_t status)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 
getHeader(uint8_t * inBuffer,uint32_t bufSize,uint32_t * headerSize,uint32_t status)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 
outputCodecData(VideoEncOutputBuffer * outBuffer)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 
outputOneNALU(VideoEncOutputBuffer * outBuffer,bool startCode)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 
outputLengthPrefixed(VideoEncOutputBuffer * outBuffer)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 
outputNaluLengthsPrefixed(VideoEncOutputBuffer * outBuffer)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 
sendEncodeCommand(EncodeTask * task)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 
renderMaxSliceSize()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 
renderCIR()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 
renderAIR()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 
calcLevel(int numMbs)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 
renderSequenceParams(EncodeTask *)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 
renderPackedSequenceParams(EncodeTask *)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 
renderPictureParams(EncodeTask * task)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 
renderPackedPictureParams(EncodeTask *)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 
renderSliceParams(EncodeTask * task)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