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