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