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 #define LOG_TAG "OMXVideoEncoderAVC" 18 #include "OMXVideoEncoderAVC.h" 19 #include "IntelMetadataBuffer.h" 20 21 static const char *AVC_MIME_TYPE = "video/h264"; 22 23 struct ProfileMap { 24 OMX_VIDEO_AVCPROFILETYPE key; 25 VAProfile value; 26 const char *name; 27 }; 28 29 struct LevelMap { 30 OMX_VIDEO_AVCLEVELTYPE key; 31 uint32_t value; 32 const char *name; 33 }; 34 35 static ProfileMap ProfileTable[] = { 36 { OMX_VIDEO_AVCProfileBaseline, VAProfileH264Baseline, "AVC Baseline" }, 37 { OMX_VIDEO_AVCProfileMain, VAProfileH264Main, "AVC Main" }, 38 { OMX_VIDEO_AVCProfileHigh, VAProfileH264High, "AVC High" }, 39 { (OMX_VIDEO_AVCPROFILETYPE) 0, (VAProfile) 0, "Not Supported" }, 40 }; 41 42 static LevelMap LevelTable[] = { 43 { OMX_VIDEO_AVCLevel4, 40, "AVC Level4" }, 44 { OMX_VIDEO_AVCLevel41, 41, "AVC Level41" }, 45 { OMX_VIDEO_AVCLevel42, 42, "AVC Level42" }, 46 { OMX_VIDEO_AVCLevel5, 50, "AVC Level5" }, 47 { OMX_VIDEO_AVCLevel51, 51, "AVC Level51" }, 48 { (OMX_VIDEO_AVCLEVELTYPE) 0, 0, "Not Supported" }, 49 }; 50 51 #define FIND_BYKEY(table, x, y) {\ 52 for(int ii = 0; ; ii++) { \ 53 if (table[ii].key == x || table[ii].key == 0) { \ 54 y = ii; \ 55 break; \ 56 } \ 57 } \ 58 }\ 59 60 #define FIND_BYVALUE(table, x, y) {\ 61 for(int ii = 0; ; ii++) { \ 62 if (table[ii].value == x || table[ii].value == 0) { \ 63 y = ii; \ 64 break; \ 65 } \ 66 } \ 67 } \ 68 69 OMXVideoEncoderAVC::OMXVideoEncoderAVC() { 70 BuildHandlerList(); 71 mVideoEncoder = createVideoEncoder(AVC_MIME_TYPE); 72 if (!mVideoEncoder) { 73 LOGE("OMX_ErrorInsufficientResources"); 74 return; 75 } 76 77 mAVCParams = new VideoParamsAVC(); 78 if (!mAVCParams) { 79 LOGE("OMX_ErrorInsufficientResources"); 80 return; 81 } 82 83 //Query supported Profile/Level 84 mPLTableCount = 0; 85 86 VAProfile profiles[MAX_H264_PROFILE] = {VAProfileH264High, VAProfileH264Main, VAProfileH264Baseline}; 87 88 VideoParamsProfileLevel pl; 89 for (int i=0; i < MAX_H264_PROFILE; i++) { 90 pl.profile = profiles[i]; 91 pl.level = 0; 92 pl.isSupported = false; 93 94 mVideoEncoder->getParameters(&pl); 95 if (pl.isSupported) { 96 uint32_t profile_index; 97 uint32_t level_index; 98 99 FIND_BYVALUE(ProfileTable, pl.profile, profile_index); 100 if (ProfileTable[profile_index].key == (OMX_VIDEO_AVCPROFILETYPE) 0) 101 continue; 102 103 FIND_BYVALUE(LevelTable, pl.level, level_index); 104 if (LevelTable[level_index].key == (OMX_VIDEO_AVCLEVELTYPE) 0) 105 continue; 106 107 mPLTable[mPLTableCount].profile = ProfileTable[profile_index].key; 108 mPLTable[mPLTableCount].level = LevelTable[level_index].key; 109 mPLTableCount ++; 110 LOGV("Support Profile:%s, Level:%s\n", ProfileTable[profile_index].name, LevelTable[level_index].name); 111 } 112 } 113 114 mEmptyEOSBuf = OMX_FALSE; 115 } 116 117 OMXVideoEncoderAVC::~OMXVideoEncoderAVC() { 118 if(mAVCParams) { 119 delete mAVCParams; 120 mAVCParams = NULL; 121 } 122 } 123 124 OMX_ERRORTYPE OMXVideoEncoderAVC::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput) { 125 // OMX_VIDEO_PARAM_AVCTYPE 126 memset(&mParamAvc, 0, sizeof(mParamAvc)); 127 SetTypeHeader(&mParamAvc, sizeof(mParamAvc)); 128 mParamAvc.nPortIndex = OUTPORT_INDEX; 129 130 if (mPLTableCount > 0) { 131 mParamAvc.eProfile = (OMX_VIDEO_AVCPROFILETYPE) mPLTable[0].profile; 132 mParamAvc.eLevel = (OMX_VIDEO_AVCLEVELTYPE)mPLTable[0].level; 133 } else { 134 LOGE("No supported profile/level\n"); 135 return OMX_ErrorUndefined; 136 } 137 mParamAvc.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 138 mParamAvc.nPFrames = 29; 139 mParamAvc.nBFrames = 0; 140 141 // OMX_NALSTREAMFORMATTYPE 142 memset(&mNalStreamFormat, 0, sizeof(mNalStreamFormat)); 143 SetTypeHeader(&mNalStreamFormat, sizeof(mNalStreamFormat)); 144 mNalStreamFormat.nPortIndex = OUTPORT_INDEX; 145 // TODO: check if this is desired Nalu Format 146 //mNalStreamFormat.eNaluFormat = OMX_NaluFormatLengthPrefixedSeparateFirstHeader; 147 // OMX_VIDEO_CONFIG_AVCINTRAPERIOD 148 memset(&mConfigAvcIntraPeriod, 0, sizeof(mConfigAvcIntraPeriod)); 149 SetTypeHeader(&mConfigAvcIntraPeriod, sizeof(mConfigAvcIntraPeriod)); 150 mConfigAvcIntraPeriod.nPortIndex = OUTPORT_INDEX; 151 // TODO: need to be populated from Video Encoder 152 mConfigAvcIntraPeriod.nIDRPeriod = 1; 153 mConfigAvcIntraPeriod.nPFrames = 29; 154 155 // OMX_VIDEO_CONFIG_NALSIZE 156 memset(&mConfigNalSize, 0, sizeof(mConfigNalSize)); 157 SetTypeHeader(&mConfigNalSize, sizeof(mConfigNalSize)); 158 mConfigNalSize.nPortIndex = OUTPORT_INDEX; 159 mConfigNalSize.nNaluBytes = 0; 160 161 // OMX_VIDEO_PARAM_INTEL_AVCVUI 162 memset(&mParamIntelAvcVui, 0, sizeof(mParamIntelAvcVui)); 163 SetTypeHeader(&mParamIntelAvcVui, sizeof(mParamIntelAvcVui)); 164 mParamIntelAvcVui.nPortIndex = OUTPORT_INDEX; 165 mParamIntelAvcVui.bVuiGeneration = OMX_FALSE; 166 167 // OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS 168 memset(&mConfigIntelSliceNumbers, 0, sizeof(mConfigIntelSliceNumbers)); 169 SetTypeHeader(&mConfigIntelSliceNumbers, sizeof(mConfigIntelSliceNumbers)); 170 mConfigIntelSliceNumbers.nPortIndex = OUTPORT_INDEX; 171 mConfigIntelSliceNumbers.nISliceNumber = 1; 172 mConfigIntelSliceNumbers.nPSliceNumber = 1; 173 174 // Override OMX_PARAM_PORTDEFINITIONTYPE 175 paramPortDefinitionOutput->nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT; 176 paramPortDefinitionOutput->nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT; 177 paramPortDefinitionOutput->nBufferSize = OUTPORT_BUFFER_SIZE; 178 paramPortDefinitionOutput->format.video.cMIMEType = (OMX_STRING)AVC_MIME_TYPE; 179 paramPortDefinitionOutput->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; 180 181 // Override OMX_VIDEO_PARAM_PROFILELEVELTYPE 182 // TODO: check if profile/level supported is correct 183 mParamProfileLevel.eProfile = mParamAvc.eProfile; 184 mParamProfileLevel.eLevel = mParamAvc.eLevel; 185 186 // Override OMX_VIDEO_PARAM_BITRATETYPE 187 mParamBitrate.nTargetBitrate = 192000; 188 189 // Override OMX_VIDEO_CONFIG_INTEL_BITRATETYPE 190 mConfigIntelBitrate.nInitialQP = 0; // Initial QP for I frames 191 192 return OMX_ErrorNone; 193 } 194 195 OMX_ERRORTYPE OMXVideoEncoderAVC::SetVideoEncoderParam(void) { 196 197 Encode_Status ret = ENCODE_SUCCESS; 198 LOGV("OMXVideoEncoderAVC::SetVideoEncoderParam"); 199 200 if (!mEncoderParams) { 201 LOGE("NULL pointer: mEncoderParams"); 202 return OMX_ErrorBadParameter; 203 } 204 205 mVideoEncoder->getParameters(mEncoderParams); 206 uint32_t index; 207 FIND_BYKEY(ProfileTable, mParamAvc.eProfile, index); 208 if (ProfileTable[index].value != 0) 209 mEncoderParams->profile = ProfileTable[index].value; 210 211 if (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) 212 mEncoderParams->intraPeriod = mParamAvc.nPFrames + mParamAvc.nBFrames; 213 else 214 mEncoderParams->intraPeriod = mParamAvc.nPFrames + 1; 215 216 // 0 - all luma and chroma block edges of the slice are filtered 217 // 1 - deblocking is disabled for all block edges of the slice 218 // 2 - all luma and chroma block edges of the slice are filtered 219 // with exception of the block edges that coincide with slice boundaries 220 mEncoderParams->disableDeblocking = 0; 221 222 OMXVideoEncoderBase::SetVideoEncoderParam(); 223 224 mVideoEncoder->getParameters(mAVCParams); 225 if(mParamIntelAvcVui.bVuiGeneration == OMX_TRUE) { 226 mAVCParams->VUIFlag = 1; 227 } 228 // For resolution below VGA, single core can hit the performance target and provide VQ gain 229 if (mEncoderParams->resolution.width <= 640 && mEncoderParams->resolution.height <= 480) { 230 mConfigIntelSliceNumbers.nISliceNumber = 1; 231 mConfigIntelSliceNumbers.nPSliceNumber = 1; 232 } 233 mAVCParams->sliceNum.iSliceNum = mConfigIntelSliceNumbers.nISliceNumber; 234 mAVCParams->sliceNum.pSliceNum = mConfigIntelSliceNumbers.nPSliceNumber; 235 mAVCParams->maxSliceSize = mConfigNalSize.nNaluBytes * 8; 236 237 if (mEncoderParams->intraPeriod == 0) { 238 mAVCParams->idrInterval = 0; 239 mAVCParams->ipPeriod = 1; 240 } else { 241 mAVCParams->idrInterval = mConfigAvcIntraPeriod.nIDRPeriod; //idrinterval 242 if (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) 243 mAVCParams->ipPeriod = mEncoderParams->intraPeriod / mParamAvc.nPFrames; 244 else 245 mAVCParams->ipPeriod = 1; 246 } 247 248 ret = mVideoEncoder ->setParameters(mAVCParams); 249 CHECK_ENCODE_STATUS("setParameters"); 250 251 LOGV("VUIFlag = %d\n", mAVCParams->VUIFlag); 252 LOGV("sliceNum.iSliceNum = %d\n", mAVCParams->sliceNum.iSliceNum); 253 LOGV("sliceNum.pSliceNum = %d\n", mAVCParams->sliceNum.pSliceNum); 254 LOGV("maxSliceSize = %d\n ", mAVCParams->maxSliceSize); 255 LOGV("intraPeriod = %d\n ", mEncoderParams->intraPeriod); 256 LOGV("idrInterval = %d\n ", mAVCParams->idrInterval); 257 LOGV("ipPeriod = %d\n ", mAVCParams->ipPeriod); 258 return OMX_ErrorNone; 259 } 260 261 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorInit(void) { 262 mCSDOutputted = OMX_FALSE; 263 mInputPictureCount = 0; 264 mFrameEncodedCount = 0; 265 return OMXVideoEncoderBase::ProcessorInit(); 266 } 267 268 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorDeinit(void) { 269 return OMXVideoEncoderBase::ProcessorDeinit(); 270 } 271 272 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorStop(void) { 273 OMX_BUFFERHEADERTYPE *omxbuf = NULL; 274 275 while(!mBFrameList.empty()) { 276 omxbuf = * mBFrameList.begin(); 277 this->ports[INPORT_INDEX]->ReturnThisBuffer(omxbuf); 278 mBFrameList.erase(mBFrameList.begin()); 279 } 280 281 mEmptyEOSBuf = OMX_FALSE; 282 return OMXVideoEncoderBase::ProcessorStop(); 283 } 284 285 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorPreEmptyBuffer(OMX_BUFFERHEADERTYPE* buffer) { 286 OMX_U32 EncodeInfo = 0; 287 OMX_U32 EncodeFrameType = 0; 288 289 uint32_t poc = 0; 290 uint32_t idrPeriod = mAVCParams->idrInterval; 291 uint32_t IntraPeriod = mEncoderParams->intraPeriod; 292 uint32_t IpPeriod = mAVCParams->ipPeriod; 293 bool BFrameEnabled = IpPeriod > 1; 294 uint32_t GOP = 0; 295 296 if (idrPeriod == 0 || IntraPeriod == 0) { 297 GOP = 0xFFFFFFFF; 298 if (IntraPeriod == 0) 299 IntraPeriod = 0xFFFFFFFF; 300 } else if (BFrameEnabled) 301 GOP = IntraPeriod*idrPeriod + 1; 302 else 303 GOP = IntraPeriod*idrPeriod; 304 305 LOGV("ProcessorPreEmptyBuffer idrPeriod=%d, IntraPeriod=%d, IpPeriod=%d, BFrameEnabled=%d\n", idrPeriod, IntraPeriod, IpPeriod, BFrameEnabled); 306 307 //decide frame type, refer Merrifield Video Encoder Driver HLD Chapter 3.17 308 poc = mInputPictureCount % GOP; 309 310 if (poc == 0 /*IDR*/) { 311 EncodeFrameType = F_IDR; 312 } else if (IntraPeriod == 1) { 313 EncodeFrameType = F_I; 314 }else if ((poc > IpPeriod) && ((poc - IpPeriod) % IntraPeriod == 0))/*I*/{ 315 EncodeFrameType = F_I; 316 if (BFrameEnabled) 317 SET_CO(EncodeInfo, CACHE_POP); 318 } else if ((poc % IpPeriod == 0) /*P*/ || (buffer->nFlags & OMX_BUFFERFLAG_EOS)/*EOS,always P*/) { 319 EncodeFrameType = F_P; 320 if (BFrameEnabled) 321 SET_CO(EncodeInfo, CACHE_POP); 322 } else { /*B*/ 323 EncodeFrameType = F_B; 324 SET_CO(EncodeInfo, CACHE_PUSH); 325 } 326 327 SET_FT(EncodeInfo, EncodeFrameType); 328 SET_FC(EncodeInfo, mInputPictureCount); 329 330 buffer->pPlatformPrivate = (OMX_PTR) EncodeInfo; 331 332 LOGV("ProcessorPreEmptyBuffer Frame %d, Type %s, EncodeInfo %x\n", mInputPictureCount, FrameTypeStr[EncodeFrameType], EncodeInfo); 333 334 mInputPictureCount ++; 335 return OMX_ErrorNone; 336 } 337 338 OMX_BOOL OMXVideoEncoderAVC::ProcessCacheOperation(OMX_BUFFERHEADERTYPE **buffers) { 339 340 OMX_BOOL Cached = OMX_FALSE; 341 342 //get frame encode info 343 Encode_Info eInfo; 344 uint32_t encodeInfo = (uint32_t) buffers[INPORT_INDEX]->pPlatformPrivate; 345 eInfo.FrameType = GET_FT(encodeInfo); 346 347 eInfo.CacheOperation = GET_CO(encodeInfo); 348 eInfo.NotStopFrame = encodeInfo & ENC_NSTOP; 349 eInfo.FrameCount = GET_FC(encodeInfo); 350 351 LOGV("ProcessCacheOperation Frame %d, type:%s, CacheOps:%s, NoSTOP=%d, EOS=%d\n", 352 eInfo.FrameCount, FrameTypeStr[eInfo.FrameType], CacheOperationStr[eInfo.CacheOperation], 353 eInfo.NotStopFrame, buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS); 354 355 OMX_BOOL emptyEOSBuf = OMX_FALSE; 356 if (buffers[INPORT_INDEX]->nFilledLen == 0 && buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS) { 357 //meet an empty EOS buffer 358 emptyEOSBuf = OMX_TRUE; 359 LOGV("ProcessCacheOperation: This frame is Empty EOS buffer\n"); 360 } 361 362 if (eInfo.CacheOperation == CACHE_NONE) { 363 //nothing to do 364 } else if (eInfo.CacheOperation == CACHE_PUSH) { 365 mBFrameList.push_front(buffers[INPORT_INDEX]); 366 Cached = OMX_TRUE; 367 LOGV("ProcessCacheOperation: This B frame is cached\n"); 368 369 } else if (eInfo.CacheOperation == CACHE_POP) { 370 eInfo.NotStopFrame = true; //it is also a nstop frame 371 372 OMX_BUFFERHEADERTYPE *omxbuf = NULL; 373 uint32_t i = 0; 374 uint32_t bframecount = mBFrameList.size(); 375 376 LOGV("BFrameList size = %d\n", bframecount); 377 378 while(!mBFrameList.empty()) { 379 /*TODO: need to handle null data buffer with EOS 380 !NULL EOS case: B1 B2 P(EOS) -> P B1 B2(EOS) 381 NULL EOS case: B1 B2 NULL(EOS) -> B2 B1 NULL(EOS) 382 */ 383 384 if (emptyEOSBuf) { 385 omxbuf = *mBFrameList.begin(); 386 ports[INPORT_INDEX]->PushThisBuffer(omxbuf); 387 mBFrameList.erase(mBFrameList.begin()); //clear it from internal queue 388 389 } else { 390 omxbuf = *mBFrameList.begin(); 391 392 if (buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS && i == 0 ) { 393 //this is final encode frame, mark it is new EOS and remove original EOS 394 omxbuf->nFlags |= OMX_BUFFERFLAG_EOS; 395 buffers[INPORT_INDEX]->nFlags &= ~OMX_BUFFERFLAG_EOS; 396 } else { 397 //all these frames except final B frame in miniGOP can't be stopped at any time 398 //to avoid not breaking miniGOP integrity 399 if (i > 0) { 400 uint32_t tmp = (uint32_t) omxbuf->pPlatformPrivate; 401 tmp |= ENC_NSTOP; 402 omxbuf->pPlatformPrivate = (OMX_PTR) tmp; 403 } 404 } 405 ports[INPORT_INDEX]->RetainThisBuffer(omxbuf, false); //push bufferq head 406 407 mBFrameList.erase(mBFrameList.begin()); //clear it from internal queue 408 } 409 410 i++; 411 } 412 413 if (emptyEOSBuf) 414 ports[INPORT_INDEX]->PushThisBuffer(buffers[INPORT_INDEX]); //put it at the tail 415 416 } else if (eInfo.CacheOperation == CACHE_RESET) { 417 // mBFrameList.clear(); 418 } 419 420 eInfo.CacheOperation = CACHE_NONE; 421 422 /* restore all states into input OMX buffer 423 */ 424 if (eInfo.NotStopFrame) 425 encodeInfo |= ENC_NSTOP; 426 else 427 encodeInfo &= ~ENC_NSTOP; 428 429 SET_CO(encodeInfo, eInfo.CacheOperation); 430 buffers[INPORT_INDEX]->pPlatformPrivate = (OMX_PTR) encodeInfo; 431 432 LOGV("ProcessCacheOperation Completed return %d\n", Cached); 433 return Cached; 434 } 435 436 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessDataRetrieve( 437 OMX_BUFFERHEADERTYPE **buffers, OMX_BOOL *outBufReturned) { 438 439 OMX_NALUFORMATSTYPE NaluFormat = mNalStreamFormat.eNaluFormat; 440 441 // NaluFormat not set, setting default 442 if (NaluFormat == 0) { 443 NaluFormat = (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader; 444 mNalStreamFormat.eNaluFormat = NaluFormat; 445 } 446 447 VideoEncOutputBuffer outBuf; 448 outBuf.data = buffers[OUTPORT_INDEX]->pBuffer; 449 outBuf.bufferSize = buffers[OUTPORT_INDEX]->nAllocLen; 450 outBuf.dataSize = 0; 451 outBuf.remainingSize = 0; 452 outBuf.flag = 0; 453 outBuf.timeStamp = 0; 454 outBuf.offset = 0; 455 456 switch (NaluFormat) { 457 case OMX_NaluFormatStartCodes: 458 outBuf.format = OUTPUT_EVERYTHING; 459 break; 460 461 case OMX_NaluFormatOneNaluPerBuffer: 462 outBuf.format = OUTPUT_ONE_NAL; 463 break; 464 465 default: 466 if (NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader|| 467 NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatLengthPrefixedSeparateFirstHeader){ 468 if(!mCSDOutputted) { 469 LOGV("Output codec data for first frame\n"); 470 outBuf.format = OUTPUT_CODEC_DATA; 471 } else { 472 if (NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader) 473 outBuf.format = OUTPUT_EVERYTHING; 474 else 475 outBuf.format = OUTPUT_NALULENGTHS_PREFIXED; 476 } 477 break; 478 } else { 479 return OMX_ErrorUndefined; 480 } 481 } 482 483 //start getOutput 484 Encode_Status ret = mVideoEncoder->getOutput(&outBuf, FUNC_NONBLOCK); 485 486 if (ret < ENCODE_SUCCESS) { 487 LOGE("libMIX getOutput Failed. ret = 0x%08x\n", ret); 488 outBuf.dataSize = 0; 489 outBuf.flag |= ENCODE_BUFFERFLAG_ENDOFFRAME; 490 if (ret == ENCODE_NO_REQUEST_DATA) { 491 if (mEmptyEOSBuf) { 492 //make sure no data encoding in HW, then emit one empty out buffer with EOS 493 outBuf.flag |= ENCODE_BUFFERFLAG_ENDOFSTREAM; 494 LOGV("no more data encoding, will signal empty EOS output buf\n"); 495 } else { 496 //if not meet Empty EOS buffer, shouldn't get this error 497 LOGE("sever error, should not happend here\n"); 498 //return OMX_ErrorUndefined; //not return error here to avoid omxcodec crash 499 } 500 } 501 502 } else if (ret == ENCODE_BUFFER_TOO_SMALL) { 503 LOGE("output buffer too small\n"); 504 // Return code could not be ENCODE_BUFFER_TOO_SMALL, or we will have dead lock issue 505 return OMX_ErrorUndefined; 506 } else if (ret == ENCODE_DATA_NOT_READY) { 507 LOGV("Call libMIX getOutput againe due to 'data not ready'\n"); 508 ret = mVideoEncoder->getOutput(&outBuf); 509 } 510 511 LOGV("libMIX getOutput data size= %d, flag=0x%08x", outBuf.dataSize, outBuf.flag); 512 OMX_U32 outfilledlen = outBuf.dataSize; 513 OMX_U32 outoffset = outBuf.offset; 514 OMX_S64 outtimestamp = outBuf.timeStamp; 515 OMX_U32 outflags = 0; 516 517 //if codecconfig 518 if (outBuf.flag & ENCODE_BUFFERFLAG_CODECCONFIG) 519 outflags |= OMX_BUFFERFLAG_CODECCONFIG; 520 521 //if syncframe 522 if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) 523 outflags |= OMX_BUFFERFLAG_SYNCFRAME; 524 525 //if eos 526 if (outBuf.flag & ENCODE_BUFFERFLAG_ENDOFSTREAM) 527 outflags |= OMX_BUFFERFLAG_EOS; 528 529 //if full encoded data retrieved 530 if(outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) { 531 LOGV("got a complete libmix Frame\n"); 532 outflags |= OMX_BUFFERFLAG_ENDOFFRAME; 533 534 if ((NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader 535 || NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatLengthPrefixedSeparateFirstHeader ) 536 && !mCSDOutputted && outfilledlen > 0) { 537 mCSDOutputted = OMX_TRUE; 538 539 } else { 540 ports[INPORT_INDEX]->ReturnOneRetainedBuffer(); //return one retained frame from head 541 mFrameOutputCount ++; 542 } 543 } 544 545 if (outfilledlen == 0) { 546 if (mEmptyEOSBuf) { 547 //emit empty EOS out buf since meet empty EOS input buf 548 buffers[OUTPORT_INDEX]->nFilledLen = 0; 549 buffers[OUTPORT_INDEX]->nTimeStamp = 0; 550 buffers[OUTPORT_INDEX]->nFlags = outflags; 551 *outBufReturned = OMX_TRUE; 552 LOGV("emit one empty EOS OMX output buf = %p:%d, flag = 0x%08x, ts=%lld", buffers[OUTPORT_INDEX]->pBuffer, outfilledlen, outflags, outtimestamp); 553 } else 554 //not emit out buf since something wrong 555 *outBufReturned = OMX_FALSE; 556 557 } else { 558 buffers[OUTPORT_INDEX]->nOffset = outoffset; 559 buffers[OUTPORT_INDEX]->nFilledLen = outfilledlen; 560 buffers[OUTPORT_INDEX]->nTimeStamp = outtimestamp; 561 buffers[OUTPORT_INDEX]->nFlags = outflags; 562 if (outBuf.flag & ENCODE_BUFFERFLAG_NSTOPFRAME) 563 buffers[OUTPORT_INDEX]->pPlatformPrivate = (OMX_PTR) 0x00000001; //indicate it is nstop frame 564 *outBufReturned = OMX_TRUE; 565 LOGV("emit one OMX output buf = %p:%d, flag = 0x%08x, ts=%lld", buffers[OUTPORT_INDEX]->pBuffer, outfilledlen, outflags, outtimestamp); 566 567 } 568 569 LOGV("ProcessDataRetrieve OK, mFrameEncodedCount=%d , mFrameOutputCount=%d\n", mFrameEncodedCount, mFrameOutputCount); 570 return OMX_ErrorNone; 571 } 572 573 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorProcess( 574 OMX_BUFFERHEADERTYPE **buffers, 575 buffer_retain_t *retains, 576 OMX_U32) { 577 578 OMX_ERRORTYPE oret = OMX_ErrorNone; 579 Encode_Status ret = ENCODE_SUCCESS; 580 581 bool FrameEncoded = false; 582 583 if (buffers[INPORT_INDEX]) { 584 LOGV("input buffer has new frame\n"); 585 586 //get frame encode info 587 Encode_Info eInfo; 588 uint32_t encodeInfo = (uint32_t) buffers[INPORT_INDEX]->pPlatformPrivate; 589 eInfo.FrameType = GET_FT(encodeInfo); 590 eInfo.CacheOperation = GET_CO(encodeInfo); 591 eInfo.NotStopFrame = encodeInfo & ENC_NSTOP; 592 eInfo.FrameCount = GET_FC(encodeInfo); 593 594 //handle frame cache operation 595 if (ProcessCacheOperation(buffers)) { 596 //frame is cached, nothing should be done in this case, just store status and return 597 retains[INPORT_INDEX] = BUFFER_RETAIN_CACHE; 598 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 599 return OMX_ErrorNone; 600 } 601 602 //try encode if frame is not cached 603 VideoEncRawBuffer inBuf; 604 605 inBuf.data = buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset; 606 inBuf.size = buffers[INPORT_INDEX]->nFilledLen; 607 inBuf.flag = 0; 608 inBuf.timeStamp = buffers[INPORT_INDEX]->nTimeStamp; 609 610 if (inBuf.size == 0 && buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS) { 611 //meet an empty EOS buffer, retain it directly and return from here 612 retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE; 613 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 614 mEmptyEOSBuf = OMX_TRUE; 615 return OMX_ErrorNone; 616 } 617 618 if (buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS) 619 inBuf.flag |= ENCODE_BUFFERFLAG_ENDOFSTREAM; 620 if (eInfo.NotStopFrame) 621 inBuf.flag |= ENCODE_BUFFERFLAG_NSTOPFRAME; 622 inBuf.type = (FrameType) eInfo.FrameType; 623 624 LOGV("start libmix encoding\n"); 625 // encode and setConfig need to be thread safe 626 pthread_mutex_lock(&mSerializationLock); 627 ret = mVideoEncoder->encode(&inBuf, FUNC_NONBLOCK); 628 pthread_mutex_unlock(&mSerializationLock); 629 LOGV("end libmix encoding\n"); 630 631 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 632 if (ret == ENCODE_DEVICE_BUSY) { 633 //encoder is busy, put buf back and come again 634 LOGV("encoder is busy, push buffer back to get again\n"); 635 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; 636 } else { 637 //if error, this buf will be returned 638 CHECK_ENCODE_STATUS("encode"); 639 640 LOGV("put buffer to encoder and retain this buffer\n"); 641 mFrameEncodedCount ++; 642 FrameEncoded = true; 643 retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE; 644 } 645 646 } else { 647 //no new coming frames, but maybe still have frames not outputted 648 LOGV("input buffer is null\n"); 649 } 650 651 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; //set to default value 652 //just call getoutput if no frame encoded in this cycle to avoid retained buffer queue wrong state 653 if (!FrameEncoded) { 654 OMX_BOOL OutBufReturned = OMX_FALSE; 655 oret = ProcessDataRetrieve(buffers, &OutBufReturned); 656 if (OutBufReturned) 657 retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 658 } 659 660 LOGV("ProcessorProcess ret=%x", oret); 661 return oret; 662 663 } 664 665 OMX_ERRORTYPE OMXVideoEncoderAVC::BuildHandlerList(void) { 666 OMXVideoEncoderBase::BuildHandlerList(); 667 AddHandler(OMX_IndexParamVideoAvc, GetParamVideoAvc, SetParamVideoAvc); 668 AddHandler((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormat, GetParamNalStreamFormat, SetParamNalStreamFormat); 669 AddHandler((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSupported, GetParamNalStreamFormatSupported, SetParamNalStreamFormatSupported); 670 AddHandler((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, GetParamNalStreamFormatSelect, SetParamNalStreamFormatSelect); 671 AddHandler(OMX_IndexConfigVideoAVCIntraPeriod, GetConfigVideoAVCIntraPeriod, SetConfigVideoAVCIntraPeriod); 672 AddHandler(OMX_IndexConfigVideoNalSize, GetConfigVideoNalSize, SetConfigVideoNalSize); 673 AddHandler((OMX_INDEXTYPE)OMX_IndexConfigIntelSliceNumbers, GetConfigIntelSliceNumbers, SetConfigIntelSliceNumbers); 674 AddHandler((OMX_INDEXTYPE)OMX_IndexParamIntelAVCVUI, GetParamIntelAVCVUI, SetParamIntelAVCVUI); 675 AddHandler((OMX_INDEXTYPE)OMX_IndexParamVideoBytestream, GetParamVideoBytestream, SetParamVideoBytestream); 676 AddHandler((OMX_INDEXTYPE)OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoProfileLevelQuerySupported, SetParamVideoProfileLevelQuerySupported); 677 return OMX_ErrorNone; 678 } 679 680 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamVideoProfileLevelQuerySupported(OMX_PTR pStructure) { 681 OMX_ERRORTYPE ret; 682 OMX_VIDEO_PARAM_PROFILELEVELTYPE *p = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pStructure; 683 CHECK_TYPE_HEADER(p); 684 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 685 686 CHECK_ENUMERATION_RANGE(p->nProfileIndex,mPLTableCount); 687 688 p->eProfile = mPLTable[p->nProfileIndex].profile; 689 p->eLevel = mPLTable[p->nProfileIndex].level; 690 691 return OMX_ErrorNone; 692 } 693 694 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamVideoProfileLevelQuerySupported(OMX_PTR) { 695 LOGW("SetParamVideoAVCProfileLevel is not supported."); 696 return OMX_ErrorUnsupportedSetting; 697 } 698 699 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamVideoAvc(OMX_PTR pStructure) { 700 OMX_ERRORTYPE ret; 701 OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure; 702 CHECK_TYPE_HEADER(p); 703 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 704 705 mVideoEncoder->getParameters(mAVCParams); 706 if(mParamAvc.eProfile == OMX_VIDEO_AVCProfileHigh) 707 { 708 mAVCParams->bEntropyCodingCABAC = 1; 709 mAVCParams->bDirect8x8Inference = 1; 710 } 711 mParamAvc.bEntropyCodingCABAC = (OMX_BOOL)mAVCParams->bEntropyCodingCABAC; 712 mParamAvc.bWeightedPPrediction = (OMX_BOOL)mAVCParams->bWeightedPPrediction; 713 mParamAvc.nRefIdx10ActiveMinus1 = mAVCParams->refIdx10ActiveMinus1; 714 mParamAvc.nRefIdx11ActiveMinus1 = mAVCParams->refIdx11ActiveMinus1; 715 mParamAvc.nWeightedBipredicitonMode = mAVCParams->weightedBipredicitonMode; 716 mParamAvc.bDirect8x8Inference = (OMX_BOOL)mAVCParams->bDirect8x8Inference; 717 mParamAvc.bDirectSpatialTemporal = (OMX_BOOL)mAVCParams->bDirectSpatialTemporal; 718 mParamAvc.nCabacInitIdc = mAVCParams->cabacInitIdc; 719 mParamAvc.bFrameMBsOnly = (OMX_BOOL)mAVCParams->bFrameMBsOnly; 720 mParamAvc.bconstIpred = (OMX_BOOL)mAVCParams->bConstIpred; 721 memcpy(p, &mParamAvc, sizeof(*p)); 722 return OMX_ErrorNone; 723 } 724 725 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamVideoAvc(OMX_PTR pStructure) { 726 OMX_ERRORTYPE ret; 727 OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure; 728 CHECK_TYPE_HEADER(p); 729 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 730 CHECK_SET_PARAM_STATE(); 731 732 //Check if parameters are valid 733 734 if(p->bEnableASO == OMX_TRUE) 735 return OMX_ErrorUnsupportedSetting; 736 737 if(p->bEnableFMO == OMX_TRUE) 738 return OMX_ErrorUnsupportedSetting; 739 740 if(p->bEnableUEP == OMX_TRUE) 741 return OMX_ErrorUnsupportedSetting; 742 743 if(p->bEnableRS == OMX_TRUE) 744 return OMX_ErrorUnsupportedSetting; 745 746 if (p->eProfile == OMX_VIDEO_AVCProfileBaseline && 747 (p->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) ) 748 return OMX_ErrorBadParameter; 749 750 if (p->nAllowedPictureTypes & OMX_VIDEO_PictureTypeP && (p->nPFrames == 0)) 751 return OMX_ErrorBadParameter; 752 753 if (p->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB ) { 754 if (p->nBFrames == 0) 755 return OMX_ErrorBadParameter; 756 757 //IpPeriod must be integer 758 uint32_t IntraPeriod = mParamAvc.nPFrames + mParamAvc.nBFrames ; 759 if (IntraPeriod % mParamAvc.nPFrames != 0) 760 return OMX_ErrorBadParameter; 761 762 //IntraPeriod must be multipe of IpPeriod. 763 uint32_t IpPeriod = IntraPeriod /mParamAvc.nPFrames; 764 if (IntraPeriod % IpPeriod != 0) 765 return OMX_ErrorBadParameter; 766 } 767 768 // TODO: do we need to check if port is enabled? 769 // TODO: see SetPortAvcParam implementation - Can we make simple copy???? 770 memcpy(&mParamAvc, p, sizeof(mParamAvc)); 771 mVideoEncoder->getParameters(mAVCParams); 772 mAVCParams->bEntropyCodingCABAC = mParamAvc.bEntropyCodingCABAC; 773 mAVCParams->bDirect8x8Inference = mParamAvc.bDirect8x8Inference; 774 if(mParamAvc.eProfile == OMX_VIDEO_AVCProfileBaseline){ 775 mAVCParams->bEntropyCodingCABAC = 0; 776 mAVCParams->bDirect8x8Inference = 0; 777 } 778 mVideoEncoder->setParameters(mAVCParams); 779 780 781 return OMX_ErrorNone; 782 } 783 784 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormat(OMX_PTR pStructure) { 785 OMX_ERRORTYPE ret; 786 OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure; 787 788 CHECK_TYPE_HEADER(p); 789 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 790 // TODO: check if this is desired format 791 p->eNaluFormat = mNalStreamFormat.eNaluFormat; //OMX_NaluFormatStartCodes; 792 return OMX_ErrorNone; 793 } 794 795 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormat(OMX_PTR pStructure) { 796 OMX_ERRORTYPE ret; 797 OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure; 798 799 CHECK_TYPE_HEADER(p); 800 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 801 LOGV("p->eNaluFormat =%d\n",p->eNaluFormat); 802 if(p->eNaluFormat != OMX_NaluFormatStartCodes && 803 p->eNaluFormat != (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader && 804 p->eNaluFormat != OMX_NaluFormatOneNaluPerBuffer && 805 p->eNaluFormat != (OMX_NALUFORMATSTYPE)OMX_NaluFormatLengthPrefixedSeparateFirstHeader) { 806 LOGE("Format not support\n"); 807 return OMX_ErrorUnsupportedSetting; 808 } 809 mNalStreamFormat.eNaluFormat = p->eNaluFormat; 810 return OMX_ErrorNone; 811 } 812 813 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormatSupported(OMX_PTR pStructure) { 814 OMX_ERRORTYPE ret; 815 OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure; 816 817 CHECK_TYPE_HEADER(p); 818 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 819 p->eNaluFormat = (OMX_NALUFORMATSTYPE) 820 (OMX_NaluFormatStartCodes | 821 OMX_NaluFormatStartCodesSeparateFirstHeader | 822 OMX_NaluFormatOneNaluPerBuffer| 823 OMX_NaluFormatLengthPrefixedSeparateFirstHeader); 824 825 // TODO: check if this is desired format 826 // OMX_NaluFormatFourByteInterleaveLength | 827 // OMX_NaluFormatZeroByteInterleaveLength); 828 return OMX_ErrorNone; 829 } 830 831 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormatSupported(OMX_PTR) { 832 LOGW("SetParamNalStreamFormatSupported is not supported."); 833 return OMX_ErrorUnsupportedSetting; 834 } 835 836 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormatSelect(OMX_PTR) { 837 LOGW("GetParamNalStreamFormatSelect is not supported."); 838 return OMX_ErrorUnsupportedSetting; 839 } 840 841 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormatSelect(OMX_PTR pStructure) { 842 OMX_ERRORTYPE ret; 843 OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure; 844 CHECK_TYPE_HEADER(p); 845 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 846 847 // return OMX_ErrorIncorrectStateOperation if not in Loaded state 848 CHECK_SET_PARAM_STATE(); 849 850 if (p->eNaluFormat != OMX_NaluFormatStartCodes && 851 p->eNaluFormat != (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader && 852 p->eNaluFormat != OMX_NaluFormatOneNaluPerBuffer&& 853 p->eNaluFormat != (OMX_NALUFORMATSTYPE)OMX_NaluFormatLengthPrefixedSeparateFirstHeader) { 854 //p->eNaluFormat != OMX_NaluFormatFourByteInterleaveLength && 855 //p->eNaluFormat != OMX_NaluFormatZeroByteInterleaveLength) { 856 // TODO: check if this is desried 857 return OMX_ErrorBadParameter; 858 } 859 860 mNalStreamFormat = *p; 861 return OMX_ErrorNone; 862 } 863 864 OMX_ERRORTYPE OMXVideoEncoderAVC::GetConfigVideoAVCIntraPeriod(OMX_PTR pStructure) { 865 OMX_ERRORTYPE ret; 866 OMX_VIDEO_CONFIG_AVCINTRAPERIOD *p = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pStructure; 867 868 CHECK_TYPE_HEADER(p); 869 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 870 // TODO: populate mConfigAvcIntraPeriod from VideoEncoder 871 // return OMX_ErrorNotReady if VideoEncoder is not created. 872 memcpy(p, &mConfigAvcIntraPeriod, sizeof(*p)); 873 return OMX_ErrorNone; 874 } 875 876 OMX_ERRORTYPE OMXVideoEncoderAVC::SetConfigVideoAVCIntraPeriod(OMX_PTR pStructure) { 877 OMX_ERRORTYPE ret; 878 Encode_Status retStatus = ENCODE_SUCCESS; 879 OMX_VIDEO_CONFIG_AVCINTRAPERIOD *p = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pStructure; 880 CHECK_TYPE_HEADER(p); 881 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 882 883 // return OMX_ErrorNone if not in Executing state 884 // TODO: return OMX_ErrorIncorrectStateOperation? 885 CHECK_SET_CONFIG_STATE(); 886 887 //check if parameters are valid 888 if ( ( (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeP) || 889 (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) ) && 890 p->nPFrames == 0 ) 891 return OMX_ErrorBadParameter; 892 893 // TODO: apply AVC Intra Period configuration in Executing state 894 VideoConfigAVCIntraPeriod avcIntraPreriod; 895 896 if (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) { 897 avcIntraPreriod.intraPeriod = p->nPFrames; 898 if (p->nPFrames % mParamAvc.nBFrames != 0) 899 return OMX_ErrorBadParameter; 900 avcIntraPreriod.ipPeriod = p->nPFrames / mParamAvc.nBFrames; 901 902 if (avcIntraPreriod.intraPeriod % avcIntraPreriod.ipPeriod != 0) 903 return OMX_ErrorBadParameter; 904 905 avcIntraPreriod.idrInterval = p->nIDRPeriod; 906 } else { 907 avcIntraPreriod.intraPeriod = p->nPFrames + 1; 908 avcIntraPreriod.ipPeriod = 1; 909 if (avcIntraPreriod.intraPeriod == 0) 910 avcIntraPreriod.idrInterval = 0; 911 else 912 avcIntraPreriod.idrInterval = p->nIDRPeriod; 913 } 914 915 retStatus = mVideoEncoder->setConfig(&avcIntraPreriod); 916 if(retStatus != ENCODE_SUCCESS) { 917 LOGW("set avc intra period config failed"); 918 } 919 920 mEncoderParams->intraPeriod = avcIntraPreriod.intraPeriod; 921 mAVCParams->idrInterval = avcIntraPreriod.idrInterval; 922 mAVCParams->ipPeriod = avcIntraPreriod.ipPeriod; 923 924 mConfigAvcIntraPeriod = *p; 925 mConfigAvcIntraPeriod.nIDRPeriod = avcIntraPreriod.idrInterval; 926 927 return OMX_ErrorNone; 928 } 929 930 OMX_ERRORTYPE OMXVideoEncoderAVC::GetConfigVideoNalSize(OMX_PTR pStructure) { 931 OMX_ERRORTYPE ret; 932 OMX_VIDEO_CONFIG_NALSIZE *p = (OMX_VIDEO_CONFIG_NALSIZE *)pStructure; 933 934 CHECK_TYPE_HEADER(p); 935 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 936 memcpy(p, &mConfigNalSize, sizeof(*p)); 937 return OMX_ErrorNone; 938 } 939 940 OMX_ERRORTYPE OMXVideoEncoderAVC::SetConfigVideoNalSize(OMX_PTR pStructure) { 941 OMX_ERRORTYPE ret; 942 Encode_Status retStatus = ENCODE_SUCCESS; 943 if (mParamBitrate.eControlRate == OMX_Video_ControlRateMax) { 944 LOGE("SetConfigVideoNalSize failed. Feature is disabled."); 945 return OMX_ErrorUnsupportedIndex; 946 } 947 OMX_VIDEO_CONFIG_NALSIZE *p = (OMX_VIDEO_CONFIG_NALSIZE *)pStructure; 948 CHECK_TYPE_HEADER(p); 949 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 950 951 // set in either Loaded state (ComponentSetParam) or Executing state (ComponentSetConfig) 952 mConfigNalSize = *p; 953 954 // return OMX_ErrorNone if not in Executing state 955 // TODO: return OMX_ErrorIncorrectStateOperation? 956 CHECK_SET_CONFIG_STATE(); 957 958 if (mParamBitrate.eControlRate != (OMX_VIDEO_CONTROLRATETYPE)OMX_Video_Intel_ControlRateVideoConferencingMode) { 959 LOGE("SetConfigVideoNalSize failed. Feature is supported only in VCM."); 960 return OMX_ErrorUnsupportedSetting; 961 } 962 VideoConfigNALSize configNalSize; 963 configNalSize.maxSliceSize = mConfigNalSize.nNaluBytes * 8; 964 retStatus = mVideoEncoder->setConfig(&configNalSize); 965 if(retStatus != ENCODE_SUCCESS) { 966 LOGW("set NAL size config failed"); 967 } 968 return OMX_ErrorNone; 969 } 970 971 OMX_ERRORTYPE OMXVideoEncoderAVC::GetConfigIntelSliceNumbers(OMX_PTR pStructure) { 972 OMX_ERRORTYPE ret; 973 OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *p = (OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *)pStructure; 974 975 CHECK_TYPE_HEADER(p); 976 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 977 memcpy(p, &mConfigIntelSliceNumbers, sizeof(*p)); 978 return OMX_ErrorNone; 979 } 980 981 OMX_ERRORTYPE OMXVideoEncoderAVC::SetConfigIntelSliceNumbers(OMX_PTR pStructure) { 982 OMX_ERRORTYPE ret; 983 Encode_Status retStatus = ENCODE_SUCCESS; 984 if (mParamBitrate.eControlRate == OMX_Video_ControlRateMax) { 985 LOGE("SetConfigIntelSliceNumbers failed. Feature is disabled."); 986 return OMX_ErrorUnsupportedIndex; 987 } 988 OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *p = (OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *)pStructure; 989 CHECK_TYPE_HEADER(p); 990 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 991 992 // set in either Loaded state (ComponentSetParam) or Executing state (ComponentSetConfig) 993 mConfigIntelSliceNumbers = *p; 994 995 // return OMX_ErrorNone if not in Executing state 996 // TODO: return OMX_ErrorIncorrectStateOperation? 997 CHECK_SET_CONFIG_STATE(); 998 999 if (mParamBitrate.eControlRate != (OMX_VIDEO_CONTROLRATETYPE)OMX_Video_Intel_ControlRateVideoConferencingMode) { 1000 LOGE("SetConfigIntelSliceNumbers failed. Feature is supported only in VCM."); 1001 return OMX_ErrorUnsupportedSetting; 1002 } 1003 VideoConfigSliceNum sliceNum; 1004 sliceNum.sliceNum.iSliceNum = mConfigIntelSliceNumbers.nISliceNumber; 1005 sliceNum.sliceNum.pSliceNum = mConfigIntelSliceNumbers.nPSliceNumber; 1006 retStatus = mVideoEncoder->setConfig(&sliceNum); 1007 if(retStatus != ENCODE_SUCCESS) { 1008 LOGW("set silce num config failed!\n"); 1009 } 1010 return OMX_ErrorNone; 1011 } 1012 1013 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamIntelAVCVUI(OMX_PTR pStructure) { 1014 1015 OMX_ERRORTYPE ret; 1016 OMX_VIDEO_PARAM_INTEL_AVCVUI *p = (OMX_VIDEO_PARAM_INTEL_AVCVUI *)pStructure; 1017 1018 CHECK_TYPE_HEADER(p); 1019 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 1020 memcpy(p, &mParamIntelAvcVui, sizeof(*p)); 1021 1022 return OMX_ErrorNone; 1023 } 1024 1025 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamIntelAVCVUI(OMX_PTR pStructure) { 1026 1027 OMX_ERRORTYPE ret; 1028 OMX_VIDEO_PARAM_INTEL_AVCVUI *p = (OMX_VIDEO_PARAM_INTEL_AVCVUI *)pStructure; 1029 CHECK_TYPE_HEADER(p); 1030 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 1031 1032 // set only in Loaded state (ComponentSetParam) 1033 CHECK_SET_PARAM_STATE(); 1034 1035 mParamIntelAvcVui = *p; 1036 return OMX_ErrorNone; 1037 } 1038 1039 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamVideoBytestream(OMX_PTR) { 1040 return OMX_ErrorUnsupportedSetting; 1041 } 1042 1043 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamVideoBytestream(OMX_PTR pStructure) { 1044 OMX_ERRORTYPE ret; 1045 OMX_VIDEO_PARAM_BYTESTREAMTYPE *p = (OMX_VIDEO_PARAM_BYTESTREAMTYPE *)pStructure; 1046 CHECK_TYPE_HEADER(p); 1047 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 1048 1049 // set only in Loaded state (ComponentSetParam) 1050 CHECK_SET_PARAM_STATE(); 1051 1052 if (p->bBytestream == OMX_TRUE) { 1053 mNalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; 1054 } else { 1055 // TODO: do we need to override the Nalu format? 1056 mNalStreamFormat.eNaluFormat = (OMX_NALUFORMATSTYPE)OMX_NaluFormatZeroByteInterleaveLength; 1057 } 1058 1059 return OMX_ErrorNone; 1060 } 1061 1062 1063 DECLARE_OMX_COMPONENT("OMX.Intel.VideoEncoder.AVC", "video_encoder.avc", OMXVideoEncoderAVC); 1064