1/* 2 * Copyright (C) 2012 The Android Open Source Project 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_NDEBUG 0 18#define LOG_TAG "SoftMPEG4Encoder" 19#include <utils/Log.h> 20#include <utils/misc.h> 21 22#include "mp4enc_api.h" 23#include "OMX_Video.h" 24 25#include <HardwareAPI.h> 26#include <MetadataBufferType.h> 27#include <media/stagefright/foundation/ADebug.h> 28#include <media/stagefright/foundation/AUtils.h> 29#include <media/stagefright/MediaDefs.h> 30#include <media/stagefright/MediaErrors.h> 31#include <media/stagefright/MetaData.h> 32#include <media/stagefright/Utils.h> 33#include <ui/Rect.h> 34#include <ui/GraphicBufferMapper.h> 35 36#include "SoftMPEG4Encoder.h" 37 38#include <inttypes.h> 39 40#ifndef INT32_MAX 41#define INT32_MAX 2147483647 42#endif 43 44namespace android { 45 46template<class T> 47static void InitOMXParams(T *params) { 48 params->nSize = sizeof(T); 49 params->nVersion.s.nVersionMajor = 1; 50 params->nVersion.s.nVersionMinor = 0; 51 params->nVersion.s.nRevision = 0; 52 params->nVersion.s.nStep = 0; 53} 54 55static const CodecProfileLevel kMPEG4ProfileLevels[] = { 56 { OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_MPEG4Level2 }, 57}; 58 59static const CodecProfileLevel kH263ProfileLevels[] = { 60 { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 }, 61}; 62 63SoftMPEG4Encoder::SoftMPEG4Encoder( 64 const char *name, 65 const char *componentRole, 66 OMX_VIDEO_CODINGTYPE codingType, 67 const char *mime, 68 const CodecProfileLevel *profileLevels, 69 size_t numProfileLevels, 70 const OMX_CALLBACKTYPE *callbacks, 71 OMX_PTR appData, 72 OMX_COMPONENTTYPE **component) 73 : SoftVideoEncoderOMXComponent( 74 name, componentRole, codingType, 75 profileLevels, numProfileLevels, 76 176 /* width */, 144 /* height */, 77 callbacks, appData, component), 78 mEncodeMode(COMBINE_MODE_WITH_ERR_RES), 79 mKeyFrameInterval(30), 80 mNumInputFrames(-1), 81 mStarted(false), 82 mSawInputEOS(false), 83 mSignalledError(false), 84 mHandle(new tagvideoEncControls), 85 mEncParams(new tagvideoEncOptions), 86 mInputFrameData(NULL) { 87 88 if (codingType == OMX_VIDEO_CodingH263) { 89 mEncodeMode = H263_MODE; 90 } 91 92 // 256 * 1024 is a magic number for PV's encoder, not sure why 93 const size_t kOutputBufferSize = 256 * 1024; 94 95 initPorts(kNumBuffers, kNumBuffers, kOutputBufferSize, mime); 96 97 ALOGI("Construct SoftMPEG4Encoder"); 98} 99 100SoftMPEG4Encoder::~SoftMPEG4Encoder() { 101 ALOGV("Destruct SoftMPEG4Encoder"); 102 releaseEncoder(); 103 List<BufferInfo *> &outQueue = getPortQueue(1); 104 List<BufferInfo *> &inQueue = getPortQueue(0); 105 CHECK(outQueue.empty()); 106 CHECK(inQueue.empty()); 107} 108 109OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() { 110 CHECK(mHandle != NULL); 111 memset(mHandle, 0, sizeof(tagvideoEncControls)); 112 113 CHECK(mEncParams != NULL); 114 memset(mEncParams, 0, sizeof(tagvideoEncOptions)); 115 if (!PVGetDefaultEncOption(mEncParams, 0)) { 116 ALOGE("Failed to get default encoding parameters"); 117 return OMX_ErrorUndefined; 118 } 119 if (mFramerate == 0) { 120 ALOGE("Framerate should not be 0"); 121 return OMX_ErrorUndefined; 122 } 123 mEncParams->encMode = mEncodeMode; 124 mEncParams->encWidth[0] = mWidth; 125 mEncParams->encHeight[0] = mHeight; 126 mEncParams->encFrameRate[0] = mFramerate >> 16; // mFramerate is in Q16 format 127 mEncParams->rcType = VBR_1; 128 mEncParams->vbvDelay = 5.0f; 129 130 // FIXME: 131 // Add more profile and level support for MPEG4 encoder 132 mEncParams->profile_level = CORE_PROFILE_LEVEL2; 133 mEncParams->packetSize = 32; 134 mEncParams->rvlcEnable = PV_OFF; 135 mEncParams->numLayers = 1; 136 mEncParams->timeIncRes = 1000; 137 mEncParams->tickPerSrc = ((int64_t)mEncParams->timeIncRes << 16) / mFramerate; 138 139 mEncParams->bitRate[0] = mBitrate; 140 mEncParams->iQuant[0] = 15; 141 mEncParams->pQuant[0] = 12; 142 mEncParams->quantType[0] = 0; 143 mEncParams->noFrameSkipped = PV_OFF; 144 145 if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) { 146 // Color conversion is needed. 147 free(mInputFrameData); 148 mInputFrameData = NULL; 149 if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) { 150 ALOGE("b/25812794, Buffer size is too big."); 151 return OMX_ErrorBadParameter; 152 } 153 mInputFrameData = 154 (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1); 155 CHECK(mInputFrameData != NULL); 156 } 157 158 // PV's MPEG4 encoder requires the video dimension of multiple 159 if (mWidth % 16 != 0 || mHeight % 16 != 0) { 160 ALOGE("Video frame size %dx%d must be a multiple of 16", 161 mWidth, mHeight); 162 return OMX_ErrorBadParameter; 163 } 164 165 // Set IDR frame refresh interval 166 mEncParams->intraPeriod = mKeyFrameInterval; 167 168 mEncParams->numIntraMB = 0; 169 mEncParams->sceneDetect = PV_ON; 170 mEncParams->searchRange = 16; 171 mEncParams->mv8x8Enable = PV_OFF; 172 mEncParams->gobHeaderInterval = 0; 173 mEncParams->useACPred = PV_ON; 174 mEncParams->intraDCVlcTh = 0; 175 176 return OMX_ErrorNone; 177} 178 179OMX_ERRORTYPE SoftMPEG4Encoder::initEncoder() { 180 CHECK(!mStarted); 181 182 OMX_ERRORTYPE errType = OMX_ErrorNone; 183 if (OMX_ErrorNone != (errType = initEncParams())) { 184 ALOGE("Failed to initialized encoder params"); 185 mSignalledError = true; 186 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 187 return errType; 188 } 189 190 if (!PVInitVideoEncoder(mHandle, mEncParams)) { 191 ALOGE("Failed to initialize the encoder"); 192 mSignalledError = true; 193 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 194 return OMX_ErrorUndefined; 195 } 196 197 mNumInputFrames = -1; // 1st buffer for codec specific data 198 mStarted = true; 199 200 return OMX_ErrorNone; 201} 202 203OMX_ERRORTYPE SoftMPEG4Encoder::releaseEncoder() { 204 if (!mStarted) { 205 return OMX_ErrorNone; 206 } 207 208 PVCleanUpVideoEncoder(mHandle); 209 210 free(mInputFrameData); 211 mInputFrameData = NULL; 212 213 delete mEncParams; 214 mEncParams = NULL; 215 216 delete mHandle; 217 mHandle = NULL; 218 219 mStarted = false; 220 221 return OMX_ErrorNone; 222} 223 224OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter( 225 OMX_INDEXTYPE index, OMX_PTR params) { 226 switch (index) { 227 case OMX_IndexParamVideoBitrate: 228 { 229 OMX_VIDEO_PARAM_BITRATETYPE *bitRate = 230 (OMX_VIDEO_PARAM_BITRATETYPE *) params; 231 232 if (!isValidOMXParam(bitRate)) { 233 return OMX_ErrorBadParameter; 234 } 235 236 if (bitRate->nPortIndex != 1) { 237 return OMX_ErrorUndefined; 238 } 239 240 bitRate->eControlRate = OMX_Video_ControlRateVariable; 241 bitRate->nTargetBitrate = mBitrate; 242 return OMX_ErrorNone; 243 } 244 245 case OMX_IndexParamVideoH263: 246 { 247 OMX_VIDEO_PARAM_H263TYPE *h263type = 248 (OMX_VIDEO_PARAM_H263TYPE *)params; 249 250 if (!isValidOMXParam(h263type)) { 251 return OMX_ErrorBadParameter; 252 } 253 254 if (h263type->nPortIndex != 1) { 255 return OMX_ErrorUndefined; 256 } 257 258 h263type->nAllowedPictureTypes = 259 (OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP); 260 h263type->eProfile = OMX_VIDEO_H263ProfileBaseline; 261 h263type->eLevel = OMX_VIDEO_H263Level45; 262 h263type->bPLUSPTYPEAllowed = OMX_FALSE; 263 h263type->bForceRoundingTypeToZero = OMX_FALSE; 264 h263type->nPictureHeaderRepetition = 0; 265 h263type->nGOBHeaderInterval = 0; 266 267 return OMX_ErrorNone; 268 } 269 270 case OMX_IndexParamVideoMpeg4: 271 { 272 OMX_VIDEO_PARAM_MPEG4TYPE *mpeg4type = 273 (OMX_VIDEO_PARAM_MPEG4TYPE *)params; 274 275 if (!isValidOMXParam(mpeg4type)) { 276 return OMX_ErrorBadParameter; 277 } 278 279 if (mpeg4type->nPortIndex != 1) { 280 return OMX_ErrorUndefined; 281 } 282 283 mpeg4type->eProfile = OMX_VIDEO_MPEG4ProfileCore; 284 mpeg4type->eLevel = OMX_VIDEO_MPEG4Level2; 285 mpeg4type->nAllowedPictureTypes = 286 (OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP); 287 mpeg4type->nBFrames = 0; 288 mpeg4type->nIDCVLCThreshold = 0; 289 mpeg4type->bACPred = OMX_TRUE; 290 mpeg4type->nMaxPacketSize = 256; 291 mpeg4type->nTimeIncRes = 1000; 292 mpeg4type->nHeaderExtension = 0; 293 mpeg4type->bReversibleVLC = OMX_FALSE; 294 295 return OMX_ErrorNone; 296 } 297 298 default: 299 return SoftVideoEncoderOMXComponent::internalGetParameter(index, params); 300 } 301} 302 303OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter( 304 OMX_INDEXTYPE index, const OMX_PTR params) { 305 int32_t indexFull = index; 306 307 switch (indexFull) { 308 case OMX_IndexParamVideoBitrate: 309 { 310 OMX_VIDEO_PARAM_BITRATETYPE *bitRate = 311 (OMX_VIDEO_PARAM_BITRATETYPE *) params; 312 313 if (!isValidOMXParam(bitRate)) { 314 return OMX_ErrorBadParameter; 315 } 316 317 if (bitRate->nPortIndex != 1 || 318 bitRate->eControlRate != OMX_Video_ControlRateVariable) { 319 return OMX_ErrorUndefined; 320 } 321 322 mBitrate = bitRate->nTargetBitrate; 323 return OMX_ErrorNone; 324 } 325 326 case OMX_IndexParamVideoH263: 327 { 328 OMX_VIDEO_PARAM_H263TYPE *h263type = 329 (OMX_VIDEO_PARAM_H263TYPE *)params; 330 331 if (!isValidOMXParam(h263type)) { 332 return OMX_ErrorBadParameter; 333 } 334 335 if (h263type->nPortIndex != 1) { 336 return OMX_ErrorUndefined; 337 } 338 339 if (h263type->eProfile != OMX_VIDEO_H263ProfileBaseline || 340 h263type->eLevel != OMX_VIDEO_H263Level45 || 341 (h263type->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) || 342 h263type->bPLUSPTYPEAllowed != OMX_FALSE || 343 h263type->bForceRoundingTypeToZero != OMX_FALSE || 344 h263type->nPictureHeaderRepetition != 0 || 345 h263type->nGOBHeaderInterval != 0) { 346 return OMX_ErrorUndefined; 347 } 348 349 return OMX_ErrorNone; 350 } 351 352 case OMX_IndexParamVideoMpeg4: 353 { 354 OMX_VIDEO_PARAM_MPEG4TYPE *mpeg4type = 355 (OMX_VIDEO_PARAM_MPEG4TYPE *)params; 356 357 if (!isValidOMXParam(mpeg4type)) { 358 return OMX_ErrorBadParameter; 359 } 360 361 if (mpeg4type->nPortIndex != 1) { 362 return OMX_ErrorUndefined; 363 } 364 365 if (mpeg4type->eProfile != OMX_VIDEO_MPEG4ProfileCore || 366 mpeg4type->eLevel != OMX_VIDEO_MPEG4Level2 || 367 (mpeg4type->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) || 368 mpeg4type->nBFrames != 0 || 369 mpeg4type->nIDCVLCThreshold != 0 || 370 mpeg4type->bACPred != OMX_TRUE || 371 mpeg4type->nMaxPacketSize != 256 || 372 mpeg4type->nTimeIncRes != 1000 || 373 mpeg4type->nHeaderExtension != 0 || 374 mpeg4type->bReversibleVLC != OMX_FALSE) { 375 return OMX_ErrorUndefined; 376 } 377 378 mKeyFrameInterval = int32_t(mpeg4type->nPFrames + 1); 379 380 return OMX_ErrorNone; 381 } 382 383 default: 384 return SoftVideoEncoderOMXComponent::internalSetParameter(index, params); 385 } 386} 387 388void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) { 389 if (mSignalledError || mSawInputEOS) { 390 return; 391 } 392 393 if (!mStarted) { 394 if (OMX_ErrorNone != initEncoder()) { 395 return; 396 } 397 } 398 399 List<BufferInfo *> &inQueue = getPortQueue(0); 400 List<BufferInfo *> &outQueue = getPortQueue(1); 401 402 while (!mSawInputEOS && !inQueue.empty() && !outQueue.empty()) { 403 BufferInfo *inInfo = *inQueue.begin(); 404 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 405 BufferInfo *outInfo = *outQueue.begin(); 406 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 407 408 outHeader->nTimeStamp = 0; 409 outHeader->nFlags = 0; 410 outHeader->nOffset = 0; 411 outHeader->nFilledLen = 0; 412 outHeader->nOffset = 0; 413 414 uint8_t *outPtr = (uint8_t *) outHeader->pBuffer; 415 int32_t dataLength = outHeader->nAllocLen; 416 417 if (mNumInputFrames < 0) { 418 if (!PVGetVolHeader(mHandle, outPtr, &dataLength, 0)) { 419 ALOGE("Failed to get VOL header"); 420 mSignalledError = true; 421 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 422 return; 423 } 424 ALOGV("Output VOL header: %d bytes", dataLength); 425 ++mNumInputFrames; 426 outHeader->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; 427 outHeader->nFilledLen = dataLength; 428 outQueue.erase(outQueue.begin()); 429 outInfo->mOwnedByUs = false; 430 notifyFillBufferDone(outHeader); 431 return; 432 } 433 434 // Save the input buffer info so that it can be 435 // passed to an output buffer 436 InputBufferInfo info; 437 info.mTimeUs = inHeader->nTimeStamp; 438 info.mFlags = inHeader->nFlags; 439 mInputBufferInfoVec.push(info); 440 441 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 442 mSawInputEOS = true; 443 } 444 445 if (inHeader->nFilledLen > 0) { 446 const uint8_t *inputData = NULL; 447 if (mInputDataIsMeta) { 448 inputData = 449 extractGraphicBuffer( 450 mInputFrameData, (mWidth * mHeight * 3) >> 1, 451 inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen, 452 mWidth, mHeight); 453 if (inputData == NULL) { 454 ALOGE("Unable to extract gralloc buffer in metadata mode"); 455 mSignalledError = true; 456 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 457 return; 458 } 459 } else { 460 inputData = (const uint8_t *)inHeader->pBuffer + inHeader->nOffset; 461 if (mColorFormat != OMX_COLOR_FormatYUV420Planar) { 462 ConvertYUV420SemiPlanarToYUV420Planar( 463 inputData, mInputFrameData, mWidth, mHeight); 464 inputData = mInputFrameData; 465 } 466 } 467 468 CHECK(inputData != NULL); 469 470 VideoEncFrameIO vin, vout; 471 memset(&vin, 0, sizeof(vin)); 472 memset(&vout, 0, sizeof(vout)); 473 vin.height = align(mHeight, 16); 474 vin.pitch = align(mWidth, 16); 475 vin.timestamp = (inHeader->nTimeStamp + 500) / 1000; // in ms 476 vin.yChan = (uint8_t *)inputData; 477 vin.uChan = vin.yChan + vin.height * vin.pitch; 478 vin.vChan = vin.uChan + ((vin.height * vin.pitch) >> 2); 479 480 ULong modTimeMs = 0; 481 int32_t nLayer = 0; 482 MP4HintTrack hintTrack; 483 if (!PVEncodeVideoFrame(mHandle, &vin, &vout, 484 &modTimeMs, outPtr, &dataLength, &nLayer) || 485 !PVGetHintTrack(mHandle, &hintTrack)) { 486 ALOGE("Failed to encode frame or get hink track at frame %" PRId64, 487 mNumInputFrames); 488 mSignalledError = true; 489 notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); 490 } 491 CHECK(NULL == PVGetOverrunBuffer(mHandle)); 492 if (hintTrack.CodeType == 0) { // I-frame serves as sync frame 493 outHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 494 } 495 496 ++mNumInputFrames; 497 } else { 498 dataLength = 0; 499 } 500 501 inQueue.erase(inQueue.begin()); 502 inInfo->mOwnedByUs = false; 503 notifyEmptyBufferDone(inHeader); 504 505 outQueue.erase(outQueue.begin()); 506 CHECK(!mInputBufferInfoVec.empty()); 507 InputBufferInfo *inputBufInfo = mInputBufferInfoVec.begin(); 508 outHeader->nTimeStamp = inputBufInfo->mTimeUs; 509 outHeader->nFlags |= (inputBufInfo->mFlags | OMX_BUFFERFLAG_ENDOFFRAME); 510 outHeader->nFilledLen = dataLength; 511 mInputBufferInfoVec.erase(mInputBufferInfoVec.begin()); 512 outInfo->mOwnedByUs = false; 513 notifyFillBufferDone(outHeader); 514 } 515} 516 517} // namespace android 518 519android::SoftOMXComponent *createSoftOMXComponent( 520 const char *name, const OMX_CALLBACKTYPE *callbacks, 521 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 522 using namespace android; 523 if (!strcmp(name, "OMX.google.h263.encoder")) { 524 return new android::SoftMPEG4Encoder( 525 name, "video_encoder.h263", OMX_VIDEO_CodingH263, MEDIA_MIMETYPE_VIDEO_H263, 526 kH263ProfileLevels, NELEM(kH263ProfileLevels), 527 callbacks, appData, component); 528 } else if (!strcmp(name, "OMX.google.mpeg4.encoder")) { 529 return new android::SoftMPEG4Encoder( 530 name, "video_encoder.mpeg4", OMX_VIDEO_CodingMPEG4, MEDIA_MIMETYPE_VIDEO_MPEG4, 531 kMPEG4ProfileLevels, NELEM(kMPEG4ProfileLevels), 532 callbacks, appData, component); 533 } else { 534 CHECK(!"Unknown component"); 535 } 536 return NULL; 537} 538