1 /* 2 * Copyright (C) 2011 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 "SoftMPEG4" 19 #include <utils/Log.h> 20 21 #include "SoftMPEG4.h" 22 23 #include <media/stagefright/foundation/ADebug.h> 24 #include <media/stagefright/MediaDefs.h> 25 #include <media/stagefright/MediaErrors.h> 26 #include <media/IOMX.h> 27 28 #include "mp4dec_api.h" 29 30 namespace android { 31 32 static const CodecProfileLevel kM4VProfileLevels[] = { 33 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0 }, 34 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0b }, 35 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1 }, 36 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level2 }, 37 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level3 }, 38 }; 39 40 static const CodecProfileLevel kH263ProfileLevels[] = { 41 { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10 }, 42 { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level20 }, 43 { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level30 }, 44 { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 }, 45 { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level10 }, 46 { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level20 }, 47 { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level30 }, 48 { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level45 }, 49 }; 50 51 template<class T> 52 static void InitOMXParams(T *params) { 53 params->nSize = sizeof(T); 54 params->nVersion.s.nVersionMajor = 1; 55 params->nVersion.s.nVersionMinor = 0; 56 params->nVersion.s.nRevision = 0; 57 params->nVersion.s.nStep = 0; 58 } 59 60 SoftMPEG4::SoftMPEG4( 61 const char *name, 62 const OMX_CALLBACKTYPE *callbacks, 63 OMX_PTR appData, 64 OMX_COMPONENTTYPE **component) 65 : SimpleSoftOMXComponent(name, callbacks, appData, component), 66 mMode(MODE_MPEG4), 67 mHandle(new tagvideoDecControls), 68 mInputBufferCount(0), 69 mWidth(352), 70 mHeight(288), 71 mCropLeft(0), 72 mCropTop(0), 73 mCropRight(mWidth - 1), 74 mCropBottom(mHeight - 1), 75 mSignalledError(false), 76 mInitialized(false), 77 mFramesConfigured(false), 78 mNumSamplesOutput(0), 79 mOutputPortSettingsChange(NONE) { 80 if (!strcmp(name, "OMX.google.h263.decoder")) { 81 mMode = MODE_H263; 82 } else { 83 CHECK(!strcmp(name, "OMX.google.mpeg4.decoder")); 84 } 85 86 initPorts(); 87 CHECK_EQ(initDecoder(), (status_t)OK); 88 } 89 90 SoftMPEG4::~SoftMPEG4() { 91 if (mInitialized) { 92 PVCleanUpVideoDecoder(mHandle); 93 } 94 95 delete mHandle; 96 mHandle = NULL; 97 } 98 99 void SoftMPEG4::initPorts() { 100 OMX_PARAM_PORTDEFINITIONTYPE def; 101 InitOMXParams(&def); 102 103 def.nPortIndex = 0; 104 def.eDir = OMX_DirInput; 105 def.nBufferCountMin = kNumInputBuffers; 106 def.nBufferCountActual = def.nBufferCountMin; 107 def.nBufferSize = 8192; 108 def.bEnabled = OMX_TRUE; 109 def.bPopulated = OMX_FALSE; 110 def.eDomain = OMX_PortDomainVideo; 111 def.bBuffersContiguous = OMX_FALSE; 112 def.nBufferAlignment = 1; 113 114 def.format.video.cMIMEType = 115 (mMode == MODE_MPEG4) 116 ? const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4) 117 : const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263); 118 119 def.format.video.pNativeRender = NULL; 120 def.format.video.nFrameWidth = mWidth; 121 def.format.video.nFrameHeight = mHeight; 122 def.format.video.nStride = def.format.video.nFrameWidth; 123 def.format.video.nSliceHeight = def.format.video.nFrameHeight; 124 def.format.video.nBitrate = 0; 125 def.format.video.xFramerate = 0; 126 def.format.video.bFlagErrorConcealment = OMX_FALSE; 127 128 def.format.video.eCompressionFormat = 129 mMode == MODE_MPEG4 ? OMX_VIDEO_CodingMPEG4 : OMX_VIDEO_CodingH263; 130 131 def.format.video.eColorFormat = OMX_COLOR_FormatUnused; 132 def.format.video.pNativeWindow = NULL; 133 134 addPort(def); 135 136 def.nPortIndex = 1; 137 def.eDir = OMX_DirOutput; 138 def.nBufferCountMin = kNumOutputBuffers; 139 def.nBufferCountActual = def.nBufferCountMin; 140 def.bEnabled = OMX_TRUE; 141 def.bPopulated = OMX_FALSE; 142 def.eDomain = OMX_PortDomainVideo; 143 def.bBuffersContiguous = OMX_FALSE; 144 def.nBufferAlignment = 2; 145 146 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW); 147 def.format.video.pNativeRender = NULL; 148 def.format.video.nFrameWidth = mWidth; 149 def.format.video.nFrameHeight = mHeight; 150 def.format.video.nStride = def.format.video.nFrameWidth; 151 def.format.video.nSliceHeight = def.format.video.nFrameHeight; 152 def.format.video.nBitrate = 0; 153 def.format.video.xFramerate = 0; 154 def.format.video.bFlagErrorConcealment = OMX_FALSE; 155 def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 156 def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; 157 def.format.video.pNativeWindow = NULL; 158 159 def.nBufferSize = 160 (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2; 161 162 addPort(def); 163 } 164 165 status_t SoftMPEG4::initDecoder() { 166 memset(mHandle, 0, sizeof(tagvideoDecControls)); 167 return OK; 168 } 169 170 OMX_ERRORTYPE SoftMPEG4::internalGetParameter( 171 OMX_INDEXTYPE index, OMX_PTR params) { 172 switch (index) { 173 case OMX_IndexParamVideoPortFormat: 174 { 175 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = 176 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; 177 178 if (formatParams->nPortIndex > 1) { 179 return OMX_ErrorUndefined; 180 } 181 182 if (formatParams->nIndex != 0) { 183 return OMX_ErrorNoMore; 184 } 185 186 if (formatParams->nPortIndex == 0) { 187 formatParams->eCompressionFormat = 188 (mMode == MODE_MPEG4) 189 ? OMX_VIDEO_CodingMPEG4 : OMX_VIDEO_CodingH263; 190 191 formatParams->eColorFormat = OMX_COLOR_FormatUnused; 192 formatParams->xFramerate = 0; 193 } else { 194 CHECK_EQ(formatParams->nPortIndex, 1u); 195 196 formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused; 197 formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar; 198 formatParams->xFramerate = 0; 199 } 200 201 return OMX_ErrorNone; 202 } 203 204 case OMX_IndexParamVideoProfileLevelQuerySupported: 205 { 206 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel = 207 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params; 208 209 if (profileLevel->nPortIndex != 0) { // Input port only 210 ALOGE("Invalid port index: %ld", profileLevel->nPortIndex); 211 return OMX_ErrorUnsupportedIndex; 212 } 213 214 size_t index = profileLevel->nProfileIndex; 215 if (mMode == MODE_H263) { 216 size_t nProfileLevels = 217 sizeof(kH263ProfileLevels) / sizeof(kH263ProfileLevels[0]); 218 if (index >= nProfileLevels) { 219 return OMX_ErrorNoMore; 220 } 221 222 profileLevel->eProfile = kH263ProfileLevels[index].mProfile; 223 profileLevel->eLevel = kH263ProfileLevels[index].mLevel; 224 } else { 225 size_t nProfileLevels = 226 sizeof(kM4VProfileLevels) / sizeof(kM4VProfileLevels[0]); 227 if (index >= nProfileLevels) { 228 return OMX_ErrorNoMore; 229 } 230 231 profileLevel->eProfile = kM4VProfileLevels[index].mProfile; 232 profileLevel->eLevel = kM4VProfileLevels[index].mLevel; 233 } 234 return OMX_ErrorNone; 235 } 236 237 default: 238 return SimpleSoftOMXComponent::internalGetParameter(index, params); 239 } 240 } 241 242 OMX_ERRORTYPE SoftMPEG4::internalSetParameter( 243 OMX_INDEXTYPE index, const OMX_PTR params) { 244 switch (index) { 245 case OMX_IndexParamStandardComponentRole: 246 { 247 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 248 (const OMX_PARAM_COMPONENTROLETYPE *)params; 249 250 if (mMode == MODE_MPEG4) { 251 if (strncmp((const char *)roleParams->cRole, 252 "video_decoder.mpeg4", 253 OMX_MAX_STRINGNAME_SIZE - 1)) { 254 return OMX_ErrorUndefined; 255 } 256 } else { 257 if (strncmp((const char *)roleParams->cRole, 258 "video_decoder.h263", 259 OMX_MAX_STRINGNAME_SIZE - 1)) { 260 return OMX_ErrorUndefined; 261 } 262 } 263 264 return OMX_ErrorNone; 265 } 266 267 case OMX_IndexParamVideoPortFormat: 268 { 269 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = 270 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; 271 272 if (formatParams->nPortIndex > 1) { 273 return OMX_ErrorUndefined; 274 } 275 276 if (formatParams->nIndex != 0) { 277 return OMX_ErrorNoMore; 278 } 279 280 return OMX_ErrorNone; 281 } 282 283 default: 284 return SimpleSoftOMXComponent::internalSetParameter(index, params); 285 } 286 } 287 288 OMX_ERRORTYPE SoftMPEG4::getConfig( 289 OMX_INDEXTYPE index, OMX_PTR params) { 290 switch (index) { 291 case OMX_IndexConfigCommonOutputCrop: 292 { 293 OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params; 294 295 if (rectParams->nPortIndex != 1) { 296 return OMX_ErrorUndefined; 297 } 298 299 rectParams->nLeft = mCropLeft; 300 rectParams->nTop = mCropTop; 301 rectParams->nWidth = mCropRight - mCropLeft + 1; 302 rectParams->nHeight = mCropBottom - mCropTop + 1; 303 304 return OMX_ErrorNone; 305 } 306 307 default: 308 return OMX_ErrorUnsupportedIndex; 309 } 310 } 311 312 void SoftMPEG4::onQueueFilled(OMX_U32 portIndex) { 313 if (mSignalledError || mOutputPortSettingsChange != NONE) { 314 return; 315 } 316 317 List<BufferInfo *> &inQueue = getPortQueue(0); 318 List<BufferInfo *> &outQueue = getPortQueue(1); 319 320 while (!inQueue.empty() && outQueue.size() == kNumOutputBuffers) { 321 BufferInfo *inInfo = *inQueue.begin(); 322 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 323 324 PortInfo *port = editPortInfo(1); 325 326 OMX_BUFFERHEADERTYPE *outHeader = 327 port->mBuffers.editItemAt(mNumSamplesOutput & 1).mHeader; 328 329 if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) { 330 inQueue.erase(inQueue.begin()); 331 inInfo->mOwnedByUs = false; 332 notifyEmptyBufferDone(inHeader); 333 334 ++mInputBufferCount; 335 336 outHeader->nFilledLen = 0; 337 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 338 339 List<BufferInfo *>::iterator it = outQueue.begin(); 340 while ((*it)->mHeader != outHeader) { 341 ++it; 342 } 343 344 BufferInfo *outInfo = *it; 345 outInfo->mOwnedByUs = false; 346 outQueue.erase(it); 347 outInfo = NULL; 348 349 notifyFillBufferDone(outHeader); 350 outHeader = NULL; 351 return; 352 } 353 354 uint8_t *bitstream = inHeader->pBuffer + inHeader->nOffset; 355 356 if (!mInitialized) { 357 uint8_t *vol_data[1]; 358 int32_t vol_size = 0; 359 360 vol_data[0] = NULL; 361 362 if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 363 vol_data[0] = bitstream; 364 vol_size = inHeader->nFilledLen; 365 } 366 367 MP4DecodingMode mode = 368 (mMode == MODE_MPEG4) ? MPEG4_MODE : H263_MODE; 369 370 Bool success = PVInitVideoDecoder( 371 mHandle, vol_data, &vol_size, 1, mWidth, mHeight, mode); 372 373 if (!success) { 374 ALOGW("PVInitVideoDecoder failed. Unsupported content?"); 375 376 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 377 mSignalledError = true; 378 return; 379 } 380 381 MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle); 382 if (mode != actualMode) { 383 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 384 mSignalledError = true; 385 return; 386 } 387 388 PVSetPostProcType((VideoDecControls *) mHandle, 0); 389 390 if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 391 inInfo->mOwnedByUs = false; 392 inQueue.erase(inQueue.begin()); 393 inInfo = NULL; 394 notifyEmptyBufferDone(inHeader); 395 inHeader = NULL; 396 } 397 398 mInitialized = true; 399 400 if (mode == MPEG4_MODE && portSettingsChanged()) { 401 return; 402 } 403 404 continue; 405 } 406 407 if (!mFramesConfigured) { 408 PortInfo *port = editPortInfo(1); 409 OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(1).mHeader; 410 411 PVSetReferenceYUV(mHandle, outHeader->pBuffer); 412 413 mFramesConfigured = true; 414 } 415 416 uint32_t useExtTimestamp = (inHeader->nOffset == 0); 417 418 // decoder deals in ms, OMX in us. 419 uint32_t timestamp = 420 useExtTimestamp ? (inHeader->nTimeStamp + 500) / 1000 : 0xFFFFFFFF; 421 422 int32_t bufferSize = inHeader->nFilledLen; 423 int32_t tmp = bufferSize; 424 425 // The PV decoder is lying to us, sometimes it'll claim to only have 426 // consumed a subset of the buffer when it clearly consumed all of it. 427 // ignore whatever it says... 428 if (PVDecodeVideoFrame( 429 mHandle, &bitstream, ×tamp, &tmp, 430 &useExtTimestamp, 431 outHeader->pBuffer) != PV_TRUE) { 432 ALOGE("failed to decode video frame."); 433 434 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 435 mSignalledError = true; 436 return; 437 } 438 439 if (portSettingsChanged()) { 440 return; 441 } 442 443 // decoder deals in ms, OMX in us. 444 outHeader->nTimeStamp = timestamp * 1000; 445 446 inHeader->nOffset += bufferSize; 447 inHeader->nFilledLen = 0; 448 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 449 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 450 } else { 451 outHeader->nFlags = 0; 452 } 453 454 if (inHeader->nFilledLen == 0) { 455 inInfo->mOwnedByUs = false; 456 inQueue.erase(inQueue.begin()); 457 inInfo = NULL; 458 notifyEmptyBufferDone(inHeader); 459 inHeader = NULL; 460 } 461 462 ++mInputBufferCount; 463 464 outHeader->nOffset = 0; 465 outHeader->nFilledLen = (mWidth * mHeight * 3) / 2; 466 467 List<BufferInfo *>::iterator it = outQueue.begin(); 468 while ((*it)->mHeader != outHeader) { 469 ++it; 470 } 471 472 BufferInfo *outInfo = *it; 473 outInfo->mOwnedByUs = false; 474 outQueue.erase(it); 475 outInfo = NULL; 476 477 notifyFillBufferDone(outHeader); 478 outHeader = NULL; 479 480 ++mNumSamplesOutput; 481 } 482 } 483 484 bool SoftMPEG4::portSettingsChanged() { 485 int32_t disp_width, disp_height; 486 PVGetVideoDimensions(mHandle, &disp_width, &disp_height); 487 488 int32_t buf_width, buf_height; 489 PVGetBufferDimensions(mHandle, &buf_width, &buf_height); 490 491 CHECK_LE(disp_width, buf_width); 492 CHECK_LE(disp_height, buf_height); 493 494 ALOGV("disp_width = %d, disp_height = %d, buf_width = %d, buf_height = %d", 495 disp_width, disp_height, buf_width, buf_height); 496 497 if (mCropRight != disp_width - 1 498 || mCropBottom != disp_height - 1) { 499 mCropLeft = 0; 500 mCropTop = 0; 501 mCropRight = disp_width - 1; 502 mCropBottom = disp_height - 1; 503 504 notify(OMX_EventPortSettingsChanged, 505 1, 506 OMX_IndexConfigCommonOutputCrop, 507 NULL); 508 } 509 510 if (buf_width != mWidth || buf_height != mHeight) { 511 mWidth = buf_width; 512 mHeight = buf_height; 513 514 updatePortDefinitions(); 515 516 if (mMode == MODE_H263) { 517 PVCleanUpVideoDecoder(mHandle); 518 519 uint8_t *vol_data[1]; 520 int32_t vol_size = 0; 521 522 vol_data[0] = NULL; 523 if (!PVInitVideoDecoder( 524 mHandle, vol_data, &vol_size, 1, mWidth, mHeight, 525 H263_MODE)) { 526 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 527 mSignalledError = true; 528 return true; 529 } 530 } 531 532 mFramesConfigured = false; 533 534 notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 535 mOutputPortSettingsChange = AWAITING_DISABLED; 536 return true; 537 } 538 539 return false; 540 } 541 542 void SoftMPEG4::onPortFlushCompleted(OMX_U32 portIndex) { 543 if (portIndex == 0 && mInitialized) { 544 CHECK_EQ((int)PVResetVideoDecoder(mHandle), (int)PV_TRUE); 545 } 546 } 547 548 void SoftMPEG4::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 549 if (portIndex != 1) { 550 return; 551 } 552 553 switch (mOutputPortSettingsChange) { 554 case NONE: 555 break; 556 557 case AWAITING_DISABLED: 558 { 559 CHECK(!enabled); 560 mOutputPortSettingsChange = AWAITING_ENABLED; 561 break; 562 } 563 564 default: 565 { 566 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 567 CHECK(enabled); 568 mOutputPortSettingsChange = NONE; 569 break; 570 } 571 } 572 } 573 574 void SoftMPEG4::updatePortDefinitions() { 575 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef; 576 def->format.video.nFrameWidth = mWidth; 577 def->format.video.nFrameHeight = mHeight; 578 def->format.video.nStride = def->format.video.nFrameWidth; 579 def->format.video.nSliceHeight = def->format.video.nFrameHeight; 580 581 def = &editPortInfo(1)->mDef; 582 def->format.video.nFrameWidth = mWidth; 583 def->format.video.nFrameHeight = mHeight; 584 def->format.video.nStride = def->format.video.nFrameWidth; 585 def->format.video.nSliceHeight = def->format.video.nFrameHeight; 586 587 def->nBufferSize = 588 (((def->format.video.nFrameWidth + 15) & -16) 589 * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2; 590 } 591 592 } // namespace android 593 594 android::SoftOMXComponent *createSoftOMXComponent( 595 const char *name, const OMX_CALLBACKTYPE *callbacks, 596 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 597 return new android::SoftMPEG4(name, callbacks, appData, component); 598 } 599 600