OMXCodec.cpp revision 53f2b2ae6417e8a32961e05cf21920c540d8b823
1/* 2 * Copyright (C) 2009 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 "OMXCodec" 19#include <utils/Log.h> 20 21#include <binder/IServiceManager.h> 22#include <binder/MemoryDealer.h> 23#include <binder/ProcessState.h> 24#include <media/IMediaPlayerService.h> 25#include <media/stagefright/ESDS.h> 26#include <media/stagefright/MediaBuffer.h> 27#include <media/stagefright/MediaBufferGroup.h> 28#include <media/stagefright/MediaDebug.h> 29#include <media/stagefright/MediaExtractor.h> 30#include <media/stagefright/MetaData.h> 31#include <media/stagefright/MmapSource.h> 32#include <media/stagefright/OMXCodec.h> 33#include <media/stagefright/Utils.h> 34#include <utils/Vector.h> 35 36#include <OMX_Audio.h> 37#include <OMX_Component.h> 38 39namespace android { 40 41struct CodecInfo { 42 const char *mime; 43 const char *codec; 44}; 45 46static const CodecInfo kDecoderInfo[] = { 47 { "image/jpeg", "OMX.TI.JPEG.decode" }, 48 { "audio/mpeg", "OMX.TI.MP3.decode" }, 49 { "audio/mpeg", "OMX.PV.mp3dec" }, 50 { "audio/3gpp", "OMX.TI.AMR.decode" }, 51 { "audio/3gpp", "OMX.PV.amrdec" }, 52 { "audio/mp4a-latm", "OMX.TI.AAC.decode" }, 53 { "audio/mp4a-latm", "OMX.PV.aacdec" }, 54 { "video/mp4v-es", "OMX.qcom.video.decoder.mpeg4" }, 55 { "video/mp4v-es", "OMX.TI.Video.Decoder" }, 56 { "video/mp4v-es", "OMX.PV.mpeg4dec" }, 57 { "video/3gpp", "OMX.qcom.video.decoder.h263" }, 58 { "video/3gpp", "OMX.TI.Video.Decoder" }, 59 { "video/3gpp", "OMX.PV.h263dec" }, 60 { "video/avc", "OMX.qcom.video.decoder.avc" }, 61 { "video/avc", "OMX.TI.Video.Decoder" }, 62 { "video/avc", "OMX.PV.avcdec" }, 63}; 64 65static const CodecInfo kEncoderInfo[] = { 66 { "audio/3gpp", "OMX.TI.AMR.encode" }, 67 { "audio/3gpp", "OMX.PV.amrencnb" }, 68 { "audio/mp4a-latm", "OMX.TI.AAC.encode" }, 69 { "audio/mp4a-latm", "OMX.PV.aacenc" }, 70 { "video/mp4v-es", "OMX.qcom.video.encoder.mpeg4" }, 71 { "video/mp4v-es", "OMX.TI.Video.encoder" }, 72 { "video/mp4v-es", "OMX.PV.mpeg4enc" }, 73 { "video/3gpp", "OMX.qcom.video.encoder.h263" }, 74 { "video/3gpp", "OMX.TI.Video.encoder" }, 75 { "video/3gpp", "OMX.PV.h263enc" }, 76 { "video/avc", "OMX.TI.Video.encoder" }, 77 { "video/avc", "OMX.PV.avcenc" }, 78}; 79 80struct OMXCodecObserver : public BnOMXObserver { 81 OMXCodecObserver(const wp<OMXCodec> &target) 82 : mTarget(target) { 83 } 84 85 // from IOMXObserver 86 virtual void on_message(const omx_message &msg) { 87 sp<OMXCodec> codec = mTarget.promote(); 88 89 if (codec.get() != NULL) { 90 codec->on_message(msg); 91 } 92 } 93 94protected: 95 virtual ~OMXCodecObserver() {} 96 97private: 98 wp<OMXCodec> mTarget; 99 100 OMXCodecObserver(const OMXCodecObserver &); 101 OMXCodecObserver &operator=(const OMXCodecObserver &); 102}; 103 104static const char *GetCodec(const CodecInfo *info, size_t numInfos, 105 const char *mime, int index) { 106 CHECK(index >= 0); 107 for(size_t i = 0; i < numInfos; ++i) { 108 if (!strcasecmp(mime, info[i].mime)) { 109 if (index == 0) { 110 return info[i].codec; 111 } 112 113 --index; 114 } 115 } 116 117 return NULL; 118} 119 120enum { 121 kAVCProfileBaseline = 0x42, 122 kAVCProfileMain = 0x4d, 123 kAVCProfileExtended = 0x58, 124 kAVCProfileHigh = 0x64, 125 kAVCProfileHigh10 = 0x6e, 126 kAVCProfileHigh422 = 0x7a, 127 kAVCProfileHigh444 = 0xf4, 128 kAVCProfileCAVLC444Intra = 0x2c 129}; 130 131static const char *AVCProfileToString(uint8_t profile) { 132 switch (profile) { 133 case kAVCProfileBaseline: 134 return "Baseline"; 135 case kAVCProfileMain: 136 return "Main"; 137 case kAVCProfileExtended: 138 return "Extended"; 139 case kAVCProfileHigh: 140 return "High"; 141 case kAVCProfileHigh10: 142 return "High 10"; 143 case kAVCProfileHigh422: 144 return "High 422"; 145 case kAVCProfileHigh444: 146 return "High 444"; 147 case kAVCProfileCAVLC444Intra: 148 return "CAVLC 444 Intra"; 149 default: return "Unknown"; 150 } 151} 152 153// static 154sp<OMXCodec> OMXCodec::Create( 155 const sp<IOMX> &omx, 156 const sp<MetaData> &meta, bool createEncoder, 157 const sp<MediaSource> &source) { 158 const char *mime; 159 bool success = meta->findCString(kKeyMIMEType, &mime); 160 CHECK(success); 161 162 const char *componentName = NULL; 163 IOMX::node_id node = 0; 164 for (int index = 0;; ++index) { 165 if (createEncoder) { 166 componentName = GetCodec( 167 kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]), 168 mime, index); 169 } else { 170 componentName = GetCodec( 171 kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]), 172 mime, index); 173 } 174 175 if (!componentName) { 176 return NULL; 177 } 178 179 LOGV("Attempting to allocate OMX node '%s'", componentName); 180 181 status_t err = omx->allocate_node(componentName, &node); 182 if (err == OK) { 183 break; 184 } 185 } 186 187 uint32_t quirks = 0; 188 if (!strcmp(componentName, "OMX.PV.avcdec")) { 189 quirks |= kWantsNALFragments; 190 } 191 if (!strcmp(componentName, "OMX.TI.MP3.decode")) { 192 quirks |= kNeedsFlushBeforeDisable; 193 } 194 if (!strcmp(componentName, "OMX.TI.AAC.decode")) { 195 quirks |= kNeedsFlushBeforeDisable; 196 quirks |= kRequiresFlushCompleteEmulation; 197 198 // The following is currently necessary for proper shutdown 199 // behaviour, but NOT enabled by default in order to make the 200 // bug reproducible... 201 // quirks |= kRequiresFlushBeforeShutdown; 202 } 203 if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) { 204 quirks |= kRequiresLoadedToIdleAfterAllocation; 205 quirks |= kRequiresAllocateBufferOnInputPorts; 206 } 207 208 sp<OMXCodec> codec = new OMXCodec( 209 omx, node, quirks, createEncoder, mime, componentName, 210 source); 211 212 uint32_t type; 213 const void *data; 214 size_t size; 215 if (meta->findData(kKeyESDS, &type, &data, &size)) { 216 ESDS esds((const char *)data, size); 217 CHECK_EQ(esds.InitCheck(), OK); 218 219 const void *codec_specific_data; 220 size_t codec_specific_data_size; 221 esds.getCodecSpecificInfo( 222 &codec_specific_data, &codec_specific_data_size); 223 224 printf("found codec-specific data of size %d\n", 225 codec_specific_data_size); 226 227 codec->addCodecSpecificData( 228 codec_specific_data, codec_specific_data_size); 229 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) { 230 printf("found avcc of size %d\n", size); 231 232 // Parse the AVCDecoderConfigurationRecord 233 234 const uint8_t *ptr = (const uint8_t *)data; 235 236 CHECK(size >= 7); 237 CHECK_EQ(ptr[0], 1); // configurationVersion == 1 238 uint8_t profile = ptr[1]; 239 uint8_t level = ptr[3]; 240 241 CHECK((ptr[4] >> 2) == 0x3f); // reserved 242 243 size_t lengthSize = 1 + (ptr[4] & 3); 244 245 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp 246 // violates it... 247 // CHECK((ptr[5] >> 5) == 7); // reserved 248 249 size_t numSeqParameterSets = ptr[5] & 31; 250 251 ptr += 6; 252 size -= 6; 253 254 for (size_t i = 0; i < numSeqParameterSets; ++i) { 255 CHECK(size >= 2); 256 size_t length = U16_AT(ptr); 257 258 ptr += 2; 259 size -= 2; 260 261 CHECK(size >= length); 262 263 codec->addCodecSpecificData(ptr, length); 264 265 ptr += length; 266 size -= length; 267 } 268 269 CHECK(size >= 1); 270 size_t numPictureParameterSets = *ptr; 271 ++ptr; 272 --size; 273 274 for (size_t i = 0; i < numPictureParameterSets; ++i) { 275 CHECK(size >= 2); 276 size_t length = U16_AT(ptr); 277 278 ptr += 2; 279 size -= 2; 280 281 CHECK(size >= length); 282 283 codec->addCodecSpecificData(ptr, length); 284 285 ptr += length; 286 size -= length; 287 } 288 289 LOGI("AVC profile = %d (%s), level = %d", 290 (int)profile, AVCProfileToString(profile), (int)level / 10); 291 292 if (!strcmp(componentName, "OMX.TI.Video.Decoder") 293 && (profile != kAVCProfileBaseline || level > 39)) { 294 // This stream exceeds the decoder's capabilities. 295 296 LOGE("Profile and/or level exceed the decoder's capabilities."); 297 return NULL; 298 } 299 } 300 301 if (!strcasecmp("audio/3gpp", mime)) { 302 codec->setAMRFormat(); 303 } 304 if (!createEncoder && !strcasecmp("audio/mp4a-latm", mime)) { 305 codec->setAACFormat(); 306 } 307 if (!strncasecmp(mime, "video/", 6)) { 308 int32_t width, height; 309 bool success = meta->findInt32(kKeyWidth, &width); 310 success = success && meta->findInt32(kKeyHeight, &height); 311 CHECK(success); 312 313 if (createEncoder) { 314 codec->setVideoInputFormat(mime, width, height); 315 } else { 316 codec->setVideoOutputFormat(mime, width, height); 317 } 318 } 319 if (!strcasecmp(mime, "image/jpeg") 320 && !strcmp(componentName, "OMX.TI.JPEG.decode")) { 321 OMX_COLOR_FORMATTYPE format = 322 OMX_COLOR_Format32bitARGB8888; 323 // OMX_COLOR_FormatYUV420PackedPlanar; 324 // OMX_COLOR_FormatCbYCrY; 325 // OMX_COLOR_FormatYUV411Planar; 326 327 int32_t width, height; 328 bool success = meta->findInt32(kKeyWidth, &width); 329 success = success && meta->findInt32(kKeyHeight, &height); 330 331 int32_t compressedSize; 332 success = success && meta->findInt32( 333 kKeyCompressedSize, &compressedSize); 334 335 CHECK(success); 336 CHECK(compressedSize > 0); 337 338 codec->setImageOutputFormat(format, width, height); 339 codec->setJPEGInputFormat(width, height, (OMX_U32)compressedSize); 340 } 341 342 codec->initOutputFormat(meta); 343 344 return codec; 345} 346 347status_t OMXCodec::setVideoPortFormatType( 348 OMX_U32 portIndex, 349 OMX_VIDEO_CODINGTYPE compressionFormat, 350 OMX_COLOR_FORMATTYPE colorFormat) { 351 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 352 format.nSize = sizeof(format); 353 format.nVersion.s.nVersionMajor = 1; 354 format.nVersion.s.nVersionMinor = 1; 355 format.nPortIndex = portIndex; 356 format.nIndex = 0; 357 bool found = false; 358 359 OMX_U32 index = 0; 360 for (;;) { 361 format.nIndex = index; 362 status_t err = mOMX->get_parameter( 363 mNode, OMX_IndexParamVideoPortFormat, 364 &format, sizeof(format)); 365 366 if (err != OK) { 367 return err; 368 } 369 370 // The following assertion is violated by TI's video decoder. 371 // CHECK_EQ(format.nIndex, index); 372 373#if 1 374 LOGI("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d", 375 portIndex, 376 index, format.eCompressionFormat, format.eColorFormat); 377#endif 378 379 if (!strcmp("OMX.TI.Video.encoder", mComponentName)) { 380 if (portIndex == kPortIndexInput 381 && colorFormat == format.eColorFormat) { 382 // eCompressionFormat does not seem right. 383 found = true; 384 break; 385 } 386 if (portIndex == kPortIndexOutput 387 && compressionFormat == format.eCompressionFormat) { 388 // eColorFormat does not seem right. 389 found = true; 390 break; 391 } 392 } 393 394 if (format.eCompressionFormat == compressionFormat 395 && format.eColorFormat == colorFormat) { 396 found = true; 397 break; 398 } 399 400 ++index; 401 } 402 403 if (!found) { 404 return UNKNOWN_ERROR; 405 } 406 407 LOGI("found a match."); 408 status_t err = mOMX->set_parameter( 409 mNode, OMX_IndexParamVideoPortFormat, 410 &format, sizeof(format)); 411 412 return err; 413} 414 415void OMXCodec::setVideoInputFormat( 416 const char *mime, OMX_U32 width, OMX_U32 height) { 417 LOGI("setVideoInputFormat width=%ld, height=%ld", width, height); 418 419 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; 420 if (!strcasecmp("video/avc", mime)) { 421 compressionFormat = OMX_VIDEO_CodingAVC; 422 } else if (!strcasecmp("video/mp4v-es", mime)) { 423 compressionFormat = OMX_VIDEO_CodingMPEG4; 424 } else if (!strcasecmp("video/3gpp", mime)) { 425 compressionFormat = OMX_VIDEO_CodingH263; 426 } else { 427 LOGE("Not a supported video mime type: %s", mime); 428 CHECK(!"Should not be here. Not a supported video mime type."); 429 } 430 431 OMX_COLOR_FORMATTYPE colorFormat = 432 0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY; 433 434 if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) { 435 colorFormat = OMX_COLOR_FormatYUV420SemiPlanar; 436 } 437 438 setVideoPortFormatType( 439 kPortIndexInput, OMX_VIDEO_CodingUnused, 440 colorFormat); 441 442 setVideoPortFormatType( 443 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 444 445 OMX_PARAM_PORTDEFINITIONTYPE def; 446 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 447 448 def.nSize = sizeof(def); 449 def.nVersion.s.nVersionMajor = 1; 450 def.nVersion.s.nVersionMinor = 1; 451 def.nPortIndex = kPortIndexOutput; 452 453 status_t err = mOMX->get_parameter( 454 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 455 456 CHECK_EQ(err, OK); 457 CHECK_EQ(def.eDomain, OMX_PortDomainVideo); 458 459 video_def->nFrameWidth = width; 460 video_def->nFrameHeight = height; 461 462 video_def->eCompressionFormat = compressionFormat; 463 video_def->eColorFormat = OMX_COLOR_FormatUnused; 464 465 err = mOMX->set_parameter( 466 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 467 CHECK_EQ(err, OK); 468 469 //////////////////////////////////////////////////////////////////////////// 470 471 def.nSize = sizeof(def); 472 def.nVersion.s.nVersionMajor = 1; 473 def.nVersion.s.nVersionMinor = 1; 474 def.nPortIndex = kPortIndexInput; 475 476 err = mOMX->get_parameter( 477 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 478 CHECK_EQ(err, OK); 479 480 def.nBufferSize = (width * height * 2); // (width * height * 3) / 2; 481 LOGI("setting nBufferSize = %ld", def.nBufferSize); 482 483 CHECK_EQ(def.eDomain, OMX_PortDomainVideo); 484 485 video_def->nFrameWidth = width; 486 video_def->nFrameHeight = height; 487 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 488 video_def->eColorFormat = colorFormat; 489 490 err = mOMX->set_parameter( 491 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 492 CHECK_EQ(err, OK); 493} 494 495void OMXCodec::setVideoOutputFormat( 496 const char *mime, OMX_U32 width, OMX_U32 height) { 497 LOGI("setVideoOutputFormat width=%ld, height=%ld", width, height); 498 499 // Enabling this code appears to be the right thing(tm), but,... 500 // the TI decoder then loses the ability to output YUV420 and only outputs 501 // YCbYCr (16bit) 502 503#if 1 504 if (!strcmp("OMX.TI.Video.Decoder", mComponentName)) { 505 OMX_PARAM_COMPONENTROLETYPE role; 506 role.nSize = sizeof(role); 507 role.nVersion.s.nVersionMajor = 1; 508 role.nVersion.s.nVersionMinor = 1; 509 510 if (!strcasecmp("video/avc", mime)) { 511 strncpy((char *)role.cRole, "video_decoder.avc", 512 OMX_MAX_STRINGNAME_SIZE - 1); 513 } else if (!strcasecmp("video/mp4v-es", mime)) { 514 strncpy((char *)role.cRole, "video_decoder.mpeg4", 515 OMX_MAX_STRINGNAME_SIZE - 1); 516 } else if (!strcasecmp("video/3gpp", mime)) { 517 strncpy((char *)role.cRole, "video_decoder.h263", 518 OMX_MAX_STRINGNAME_SIZE - 1); 519 } 520 521 role.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 522 523 status_t err = mOMX->set_parameter( 524 mNode, OMX_IndexParamStandardComponentRole, 525 &role, sizeof(role)); 526 CHECK_EQ(err, OK); 527 } 528#endif 529 530 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; 531 if (!strcasecmp("video/avc", mime)) { 532 compressionFormat = OMX_VIDEO_CodingAVC; 533 } else if (!strcasecmp("video/mp4v-es", mime)) { 534 compressionFormat = OMX_VIDEO_CodingMPEG4; 535 } else if (!strcasecmp("video/3gpp", mime)) { 536 compressionFormat = OMX_VIDEO_CodingH263; 537 } else { 538 LOGE("Not a supported video mime type: %s", mime); 539 CHECK(!"Should not be here. Not a supported video mime type."); 540 } 541 542 setVideoPortFormatType( 543 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 544 545#if 1 546 { 547 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 548 format.nSize = sizeof(format); 549 format.nVersion.s.nVersionMajor = 1; 550 format.nVersion.s.nVersionMinor = 1; 551 format.nPortIndex = kPortIndexOutput; 552 format.nIndex = 0; 553 554 status_t err = mOMX->get_parameter( 555 mNode, OMX_IndexParamVideoPortFormat, 556 &format, sizeof(format)); 557 CHECK_EQ(err, OK); 558 CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused); 559 560 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; 561 562 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar 563 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 564 || format.eColorFormat == OMX_COLOR_FormatCbYCrY 565 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); 566 567 err = mOMX->set_parameter( 568 mNode, OMX_IndexParamVideoPortFormat, 569 &format, sizeof(format)); 570 CHECK_EQ(err, OK); 571 } 572#endif 573 574 OMX_PARAM_PORTDEFINITIONTYPE def; 575 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 576 577 def.nSize = sizeof(def); 578 def.nVersion.s.nVersionMajor = 1; 579 def.nVersion.s.nVersionMinor = 1; 580 def.nPortIndex = kPortIndexInput; 581 582 status_t err = mOMX->get_parameter( 583 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 584 585 CHECK_EQ(err, OK); 586 587#if 1 588 // XXX Need a (much) better heuristic to compute input buffer sizes. 589 const size_t X = 64 * 1024; 590 if (def.nBufferSize < X) { 591 def.nBufferSize = X; 592 } 593#endif 594 595 CHECK_EQ(def.eDomain, OMX_PortDomainVideo); 596 597 video_def->nFrameWidth = width; 598 video_def->nFrameHeight = height; 599 600 video_def->eColorFormat = OMX_COLOR_FormatUnused; 601 602 err = mOMX->set_parameter( 603 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 604 CHECK_EQ(err, OK); 605 606 //////////////////////////////////////////////////////////////////////////// 607 608 def.nSize = sizeof(def); 609 def.nVersion.s.nVersionMajor = 1; 610 def.nVersion.s.nVersionMinor = 1; 611 def.nPortIndex = kPortIndexOutput; 612 613 err = mOMX->get_parameter( 614 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 615 CHECK_EQ(err, OK); 616 CHECK_EQ(def.eDomain, OMX_PortDomainVideo); 617 618#if 0 619 def.nBufferSize = 620 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420 621#endif 622 623 video_def->nFrameWidth = width; 624 video_def->nFrameHeight = height; 625 626 err = mOMX->set_parameter( 627 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 628 CHECK_EQ(err, OK); 629} 630 631 632OMXCodec::OMXCodec( 633 const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks, 634 bool isEncoder, 635 const char *mime, 636 const char *componentName, 637 const sp<MediaSource> &source) 638 : mOMX(omx), 639 mNode(node), 640 mQuirks(quirks), 641 mIsEncoder(isEncoder), 642 mMIME(strdup(mime)), 643 mComponentName(strdup(componentName)), 644 mSource(source), 645 mCodecSpecificDataIndex(0), 646 mState(LOADED), 647 mInitialBufferSubmit(true), 648 mSignalledEOS(false), 649 mNoMoreOutputData(false), 650 mSeekTimeUs(-1) { 651 mPortStatus[kPortIndexInput] = ENABLED; 652 mPortStatus[kPortIndexOutput] = ENABLED; 653 654 mObserver = new OMXCodecObserver(this); 655 mOMX->observe_node(mNode, mObserver); 656} 657 658OMXCodec::~OMXCodec() { 659 CHECK(mState == LOADED || mState == ERROR); 660 661 status_t err = mOMX->observe_node(mNode, NULL); 662 CHECK_EQ(err, OK); 663 664 err = mOMX->free_node(mNode); 665 CHECK_EQ(err, OK); 666 667 mNode = NULL; 668 setState(DEAD); 669 670 clearCodecSpecificData(); 671 672 free(mComponentName); 673 mComponentName = NULL; 674 675 free(mMIME); 676 mMIME = NULL; 677} 678 679status_t OMXCodec::init() { 680 // mLock is held. 681 682 CHECK_EQ(mState, LOADED); 683 684 status_t err; 685 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) { 686 err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle); 687 CHECK_EQ(err, OK); 688 689 setState(LOADED_TO_IDLE); 690 } 691 692 err = allocateBuffers(); 693 CHECK_EQ(err, OK); 694 695 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) { 696 err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle); 697 CHECK_EQ(err, OK); 698 699 setState(LOADED_TO_IDLE); 700 } 701 702 while (mState != EXECUTING && mState != ERROR) { 703 mAsyncCompletion.wait(mLock); 704 } 705 706 return mState == ERROR ? UNKNOWN_ERROR : OK; 707} 708 709// static 710bool OMXCodec::isIntermediateState(State state) { 711 return state == LOADED_TO_IDLE 712 || state == IDLE_TO_EXECUTING 713 || state == EXECUTING_TO_IDLE 714 || state == IDLE_TO_LOADED 715 || state == RECONFIGURING; 716} 717 718status_t OMXCodec::allocateBuffers() { 719 status_t err = allocateBuffersOnPort(kPortIndexInput); 720 721 if (err != OK) { 722 return err; 723 } 724 725 return allocateBuffersOnPort(kPortIndexOutput); 726} 727 728status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) { 729 OMX_PARAM_PORTDEFINITIONTYPE def; 730 def.nSize = sizeof(def); 731 def.nVersion.s.nVersionMajor = 1; 732 def.nVersion.s.nVersionMinor = 1; 733 def.nVersion.s.nRevision = 0; 734 def.nVersion.s.nStep = 0; 735 def.nPortIndex = portIndex; 736 737 status_t err = mOMX->get_parameter( 738 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 739 740 if (err != OK) { 741 return err; 742 } 743 744 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 745 mDealer[portIndex] = new MemoryDealer(totalSize); 746 747 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 748 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 749 CHECK(mem.get() != NULL); 750 751 IOMX::buffer_id buffer; 752 if (portIndex == kPortIndexInput 753 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) { 754 err = mOMX->allocate_buffer_with_backup( 755 mNode, portIndex, mem, &buffer); 756 } else if (portIndex == kPortIndexOutput 757 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) { 758 err = mOMX->allocate_buffer( 759 mNode, portIndex, def.nBufferSize, &buffer); 760 } else { 761 err = mOMX->use_buffer(mNode, portIndex, mem, &buffer); 762 } 763 764 if (err != OK) { 765 LOGE("allocate_buffer_with_backup failed"); 766 return err; 767 } 768 769 BufferInfo info; 770 info.mBuffer = buffer; 771 info.mOwnedByComponent = false; 772 info.mMem = mem; 773 info.mMediaBuffer = NULL; 774 775 if (portIndex == kPortIndexOutput) { 776 info.mMediaBuffer = new MediaBuffer(mem->pointer(), mem->size()); 777 info.mMediaBuffer->setObserver(this); 778 } 779 780 mPortBuffers[portIndex].push(info); 781 782 LOGV("allocated buffer %p on %s port", buffer, 783 portIndex == kPortIndexInput ? "input" : "output"); 784 } 785 786 dumpPortStatus(portIndex); 787 788 return OK; 789} 790 791void OMXCodec::on_message(const omx_message &msg) { 792 Mutex::Autolock autoLock(mLock); 793 794 switch (msg.type) { 795 case omx_message::EVENT: 796 { 797 onEvent( 798 msg.u.event_data.event, msg.u.event_data.data1, 799 msg.u.event_data.data2); 800 801 break; 802 } 803 804 case omx_message::EMPTY_BUFFER_DONE: 805 { 806 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer; 807 808 LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer); 809 810 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput]; 811 size_t i = 0; 812 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) { 813 ++i; 814 } 815 816 CHECK(i < buffers->size()); 817 if (!(*buffers)[i].mOwnedByComponent) { 818 LOGW("We already own input buffer %p, yet received " 819 "an EMPTY_BUFFER_DONE.", buffer); 820 } 821 822 buffers->editItemAt(i).mOwnedByComponent = false; 823 824 if (mPortStatus[kPortIndexInput] == DISABLING) { 825 LOGV("Port is disabled, freeing buffer %p", buffer); 826 827 status_t err = 828 mOMX->free_buffer(mNode, kPortIndexInput, buffer); 829 CHECK_EQ(err, OK); 830 831 buffers->removeAt(i); 832 } else if (mPortStatus[kPortIndexInput] != SHUTTING_DOWN) { 833 CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED); 834 drainInputBuffer(&buffers->editItemAt(i)); 835 } 836 837 break; 838 } 839 840 case omx_message::FILL_BUFFER_DONE: 841 { 842 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer; 843 OMX_U32 flags = msg.u.extended_buffer_data.flags; 844 845 LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx)", 846 buffer, 847 msg.u.extended_buffer_data.range_length, 848 flags); 849 850 LOGV("FILL_BUFFER_DONE(timestamp: %lld us (%.2f secs))", 851 msg.u.extended_buffer_data.timestamp, 852 msg.u.extended_buffer_data.timestamp / 1E6); 853 854 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput]; 855 size_t i = 0; 856 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) { 857 ++i; 858 } 859 860 CHECK(i < buffers->size()); 861 BufferInfo *info = &buffers->editItemAt(i); 862 863 if (!info->mOwnedByComponent) { 864 LOGW("We already own output buffer %p, yet received " 865 "a FILL_BUFFER_DONE.", buffer); 866 } 867 868 info->mOwnedByComponent = false; 869 870 if (mPortStatus[kPortIndexOutput] == DISABLING) { 871 LOGV("Port is disabled, freeing buffer %p", buffer); 872 873 status_t err = 874 mOMX->free_buffer(mNode, kPortIndexOutput, buffer); 875 CHECK_EQ(err, OK); 876 877 buffers->removeAt(i); 878 } else if (mPortStatus[kPortIndexOutput] == ENABLED 879 && (flags & OMX_BUFFERFLAG_EOS)) { 880 LOGV("No more output data."); 881 mNoMoreOutputData = true; 882 mBufferFilled.signal(); 883 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) { 884 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED); 885 886 MediaBuffer *buffer = info->mMediaBuffer; 887 888 buffer->set_range( 889 msg.u.extended_buffer_data.range_offset, 890 msg.u.extended_buffer_data.range_length); 891 892 buffer->meta_data()->clear(); 893 894 buffer->meta_data()->setInt32( 895 kKeyTimeUnits, 896 (msg.u.extended_buffer_data.timestamp + 500) / 1000); 897 898 buffer->meta_data()->setInt32( 899 kKeyTimeScale, 1000); 900 901 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) { 902 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true); 903 } 904 905 buffer->meta_data()->setPointer( 906 kKeyPlatformPrivate, 907 msg.u.extended_buffer_data.platform_private); 908 909 buffer->meta_data()->setPointer( 910 kKeyBufferID, 911 msg.u.extended_buffer_data.buffer); 912 913 mFilledBuffers.push_back(i); 914 mBufferFilled.signal(); 915 } 916 917 break; 918 } 919 920 default: 921 { 922 CHECK(!"should not be here."); 923 break; 924 } 925 } 926} 927 928void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 929 switch (event) { 930 case OMX_EventCmdComplete: 931 { 932 onCmdComplete((OMX_COMMANDTYPE)data1, data2); 933 break; 934 } 935 936 case OMX_EventError: 937 { 938 LOGE("ERROR(%ld, %ld)", data1, data2); 939 940 setState(ERROR); 941 break; 942 } 943 944 case OMX_EventPortSettingsChanged: 945 { 946 onPortSettingsChanged(data1); 947 break; 948 } 949 950 case OMX_EventBufferFlag: 951 { 952 LOGV("EVENT_BUFFER_FLAG(%ld)", data1); 953 954 if (data1 == kPortIndexOutput) { 955 mNoMoreOutputData = true; 956 } 957 break; 958 } 959 960 default: 961 { 962 LOGV("EVENT(%d, %ld, %ld)", event, data1, data2); 963 break; 964 } 965 } 966} 967 968void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { 969 switch (cmd) { 970 case OMX_CommandStateSet: 971 { 972 onStateChange((OMX_STATETYPE)data); 973 break; 974 } 975 976 case OMX_CommandPortDisable: 977 { 978 OMX_U32 portIndex = data; 979 LOGV("PORT_DISABLED(%ld)", portIndex); 980 981 CHECK(mState == EXECUTING || mState == RECONFIGURING); 982 CHECK_EQ(mPortStatus[portIndex], DISABLING); 983 CHECK_EQ(mPortBuffers[portIndex].size(), 0); 984 985 mPortStatus[portIndex] = DISABLED; 986 987 if (mState == RECONFIGURING) { 988 CHECK_EQ(portIndex, kPortIndexOutput); 989 990 enablePortAsync(portIndex); 991 992 status_t err = allocateBuffersOnPort(portIndex); 993 CHECK_EQ(err, OK); 994 } 995 break; 996 } 997 998 case OMX_CommandPortEnable: 999 { 1000 OMX_U32 portIndex = data; 1001 LOGV("PORT_ENABLED(%ld)", portIndex); 1002 1003 CHECK(mState == EXECUTING || mState == RECONFIGURING); 1004 CHECK_EQ(mPortStatus[portIndex], ENABLING); 1005 1006 mPortStatus[portIndex] = ENABLED; 1007 1008 if (mState == RECONFIGURING) { 1009 CHECK_EQ(portIndex, kPortIndexOutput); 1010 1011 setState(EXECUTING); 1012 1013 fillOutputBuffers(); 1014 } 1015 break; 1016 } 1017 1018 case OMX_CommandFlush: 1019 { 1020 OMX_U32 portIndex = data; 1021 1022 LOGV("FLUSH_DONE(%ld)", portIndex); 1023 1024 CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN); 1025 mPortStatus[portIndex] = ENABLED; 1026 1027 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]), 1028 mPortBuffers[portIndex].size()); 1029 1030 if (mState == RECONFIGURING) { 1031 CHECK_EQ(portIndex, kPortIndexOutput); 1032 1033 disablePortAsync(portIndex); 1034 } else if (mState == EXECUTING_TO_IDLE) { 1035 if (mPortStatus[kPortIndexInput] == ENABLED 1036 && mPortStatus[kPortIndexOutput] == ENABLED) { 1037 LOGV("Finished flushing both ports, now completing " 1038 "transition from EXECUTING to IDLE."); 1039 1040 mPortStatus[kPortIndexInput] = SHUTTING_DOWN; 1041 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN; 1042 1043 status_t err = 1044 mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle); 1045 CHECK_EQ(err, OK); 1046 } 1047 } else { 1048 // We're flushing both ports in preparation for seeking. 1049 1050 if (mPortStatus[kPortIndexInput] == ENABLED 1051 && mPortStatus[kPortIndexOutput] == ENABLED) { 1052 LOGV("Finished flushing both ports, now continuing from" 1053 " seek-time."); 1054 1055 drainInputBuffers(); 1056 fillOutputBuffers(); 1057 } 1058 } 1059 1060 break; 1061 } 1062 1063 default: 1064 { 1065 LOGV("CMD_COMPLETE(%d, %ld)", cmd, data); 1066 break; 1067 } 1068 } 1069} 1070 1071void OMXCodec::onStateChange(OMX_STATETYPE newState) { 1072 switch (newState) { 1073 case OMX_StateIdle: 1074 { 1075 LOGV("Now Idle."); 1076 if (mState == LOADED_TO_IDLE) { 1077 status_t err = mOMX->send_command( 1078 mNode, OMX_CommandStateSet, OMX_StateExecuting); 1079 1080 CHECK_EQ(err, OK); 1081 1082 setState(IDLE_TO_EXECUTING); 1083 } else { 1084 CHECK_EQ(mState, EXECUTING_TO_IDLE); 1085 1086 CHECK_EQ( 1087 countBuffersWeOwn(mPortBuffers[kPortIndexInput]), 1088 mPortBuffers[kPortIndexInput].size()); 1089 1090 CHECK_EQ( 1091 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]), 1092 mPortBuffers[kPortIndexOutput].size()); 1093 1094 status_t err = mOMX->send_command( 1095 mNode, OMX_CommandStateSet, OMX_StateLoaded); 1096 1097 CHECK_EQ(err, OK); 1098 1099 err = freeBuffersOnPort(kPortIndexInput); 1100 CHECK_EQ(err, OK); 1101 1102 err = freeBuffersOnPort(kPortIndexOutput); 1103 CHECK_EQ(err, OK); 1104 1105 mPortStatus[kPortIndexInput] = ENABLED; 1106 mPortStatus[kPortIndexOutput] = ENABLED; 1107 1108 setState(IDLE_TO_LOADED); 1109 } 1110 break; 1111 } 1112 1113 case OMX_StateExecuting: 1114 { 1115 CHECK_EQ(mState, IDLE_TO_EXECUTING); 1116 1117 LOGV("Now Executing."); 1118 1119 setState(EXECUTING); 1120 1121 // Buffers will be submitted to the component in the first 1122 // call to OMXCodec::read as mInitialBufferSubmit is true at 1123 // this point. This ensures that this on_message call returns, 1124 // releases the lock and ::init can notice the state change and 1125 // itself return. 1126 break; 1127 } 1128 1129 case OMX_StateLoaded: 1130 { 1131 CHECK_EQ(mState, IDLE_TO_LOADED); 1132 1133 LOGV("Now Loaded."); 1134 1135 setState(LOADED); 1136 break; 1137 } 1138 1139 default: 1140 { 1141 CHECK(!"should not be here."); 1142 break; 1143 } 1144 } 1145} 1146 1147// static 1148size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) { 1149 size_t n = 0; 1150 for (size_t i = 0; i < buffers.size(); ++i) { 1151 if (!buffers[i].mOwnedByComponent) { 1152 ++n; 1153 } 1154 } 1155 1156 return n; 1157} 1158 1159status_t OMXCodec::freeBuffersOnPort( 1160 OMX_U32 portIndex, bool onlyThoseWeOwn) { 1161 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1162 1163 status_t stickyErr = OK; 1164 1165 for (size_t i = buffers->size(); i-- > 0;) { 1166 BufferInfo *info = &buffers->editItemAt(i); 1167 1168 if (onlyThoseWeOwn && info->mOwnedByComponent) { 1169 continue; 1170 } 1171 1172 CHECK_EQ(info->mOwnedByComponent, false); 1173 1174 status_t err = 1175 mOMX->free_buffer(mNode, portIndex, info->mBuffer); 1176 1177 if (err != OK) { 1178 stickyErr = err; 1179 } 1180 1181 if (info->mMediaBuffer != NULL) { 1182 info->mMediaBuffer->setObserver(NULL); 1183 1184 // Make sure nobody but us owns this buffer at this point. 1185 CHECK_EQ(info->mMediaBuffer->refcount(), 0); 1186 1187 info->mMediaBuffer->release(); 1188 } 1189 1190 buffers->removeAt(i); 1191 } 1192 1193 CHECK(onlyThoseWeOwn || buffers->isEmpty()); 1194 1195 return stickyErr; 1196} 1197 1198void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) { 1199 LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex); 1200 1201 CHECK_EQ(mState, EXECUTING); 1202 CHECK_EQ(portIndex, kPortIndexOutput); 1203 setState(RECONFIGURING); 1204 1205 if (mQuirks & kNeedsFlushBeforeDisable) { 1206 if (!flushPortAsync(portIndex)) { 1207 onCmdComplete(OMX_CommandFlush, portIndex); 1208 } 1209 } else { 1210 disablePortAsync(portIndex); 1211 } 1212} 1213 1214bool OMXCodec::flushPortAsync(OMX_U32 portIndex) { 1215 CHECK(mState == EXECUTING || mState == RECONFIGURING 1216 || mState == EXECUTING_TO_IDLE); 1217 1218 LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.", 1219 portIndex, countBuffersWeOwn(mPortBuffers[portIndex]), 1220 mPortBuffers[portIndex].size()); 1221 1222 CHECK_EQ(mPortStatus[portIndex], ENABLED); 1223 mPortStatus[portIndex] = SHUTTING_DOWN; 1224 1225 if ((mQuirks & kRequiresFlushCompleteEmulation) 1226 && countBuffersWeOwn(mPortBuffers[portIndex]) 1227 == mPortBuffers[portIndex].size()) { 1228 // No flush is necessary and this component fails to send a 1229 // flush-complete event in this case. 1230 1231 return false; 1232 } 1233 1234 status_t err = 1235 mOMX->send_command(mNode, OMX_CommandFlush, portIndex); 1236 CHECK_EQ(err, OK); 1237 1238 return true; 1239} 1240 1241void OMXCodec::disablePortAsync(OMX_U32 portIndex) { 1242 CHECK(mState == EXECUTING || mState == RECONFIGURING); 1243 1244 CHECK_EQ(mPortStatus[portIndex], ENABLED); 1245 mPortStatus[portIndex] = DISABLING; 1246 1247 status_t err = 1248 mOMX->send_command(mNode, OMX_CommandPortDisable, portIndex); 1249 CHECK_EQ(err, OK); 1250 1251 freeBuffersOnPort(portIndex, true); 1252} 1253 1254void OMXCodec::enablePortAsync(OMX_U32 portIndex) { 1255 CHECK(mState == EXECUTING || mState == RECONFIGURING); 1256 1257 CHECK_EQ(mPortStatus[portIndex], DISABLED); 1258 mPortStatus[portIndex] = ENABLING; 1259 1260 status_t err = 1261 mOMX->send_command(mNode, OMX_CommandPortEnable, portIndex); 1262 CHECK_EQ(err, OK); 1263} 1264 1265void OMXCodec::fillOutputBuffers() { 1266 CHECK_EQ(mState, EXECUTING); 1267 1268 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput]; 1269 for (size_t i = 0; i < buffers->size(); ++i) { 1270 fillOutputBuffer(&buffers->editItemAt(i)); 1271 } 1272} 1273 1274void OMXCodec::drainInputBuffers() { 1275 CHECK(mState == EXECUTING || mState == RECONFIGURING); 1276 1277 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput]; 1278 for (size_t i = 0; i < buffers->size(); ++i) { 1279 drainInputBuffer(&buffers->editItemAt(i)); 1280 } 1281} 1282 1283void OMXCodec::drainInputBuffer(BufferInfo *info) { 1284 CHECK_EQ(info->mOwnedByComponent, false); 1285 1286 if (mSignalledEOS) { 1287 return; 1288 } 1289 1290 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) { 1291 const CodecSpecificData *specific = 1292 mCodecSpecificData[mCodecSpecificDataIndex]; 1293 1294 size_t size = specific->mSize; 1295 1296 if (!strcasecmp("video/avc", mMIME) 1297 && !(mQuirks & kWantsNALFragments)) { 1298 static const uint8_t kNALStartCode[4] = 1299 { 0x00, 0x00, 0x00, 0x01 }; 1300 1301 CHECK(info->mMem->size() >= specific->mSize + 4); 1302 1303 size += 4; 1304 1305 memcpy(info->mMem->pointer(), kNALStartCode, 4); 1306 memcpy((uint8_t *)info->mMem->pointer() + 4, 1307 specific->mData, specific->mSize); 1308 } else { 1309 CHECK(info->mMem->size() >= specific->mSize); 1310 memcpy(info->mMem->pointer(), specific->mData, specific->mSize); 1311 } 1312 1313 mOMX->empty_buffer( 1314 mNode, info->mBuffer, 0, size, 1315 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG, 1316 0); 1317 1318 info->mOwnedByComponent = true; 1319 1320 ++mCodecSpecificDataIndex; 1321 return; 1322 } 1323 1324 // We're going to temporarily give up the lock while reading data 1325 // from the source. A certain client unfortunately chose to have the 1326 // thread supplying input data and reading output data be the same... 1327 1328 MediaBuffer *srcBuffer; 1329 status_t err; 1330 if (mSeekTimeUs >= 0) { 1331 MediaSource::ReadOptions options; 1332 options.setSeekTo(mSeekTimeUs); 1333 mSeekTimeUs = -1; 1334 1335 mLock.unlock(); 1336 err = mSource->read(&srcBuffer, &options); 1337 } else { 1338 mLock.unlock(); 1339 err = mSource->read(&srcBuffer); 1340 } 1341 mLock.lock(); 1342 1343 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 1344 OMX_TICKS timestamp = 0; 1345 size_t srcLength = 0; 1346 1347 if (err != OK) { 1348 LOGV("signalling end of input stream."); 1349 flags |= OMX_BUFFERFLAG_EOS; 1350 1351 mSignalledEOS = true; 1352 } else { 1353 srcLength = srcBuffer->range_length(); 1354 1355 if (info->mMem->size() < srcLength) { 1356 LOGE("info->mMem->size() = %d, srcLength = %d", 1357 info->mMem->size(), srcLength); 1358 } 1359 CHECK(info->mMem->size() >= srcLength); 1360 memcpy(info->mMem->pointer(), 1361 (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(), 1362 srcLength); 1363 1364 int32_t units, scale; 1365 if (srcBuffer->meta_data()->findInt32(kKeyTimeUnits, &units) 1366 && srcBuffer->meta_data()->findInt32(kKeyTimeScale, &scale)) { 1367 timestamp = ((OMX_TICKS)units * 1000000) / scale; 1368 1369 LOGV("Calling empty_buffer on buffer %p (length %d)", 1370 info->mBuffer, srcLength); 1371 LOGV("Calling empty_buffer with timestamp %lld us (%.2f secs)", 1372 timestamp, timestamp / 1E6); 1373 } 1374 } 1375 1376 mOMX->empty_buffer( 1377 mNode, info->mBuffer, 0, srcLength, 1378 flags, timestamp); 1379 1380 info->mOwnedByComponent = true; 1381 1382 if (srcBuffer != NULL) { 1383 srcBuffer->release(); 1384 srcBuffer = NULL; 1385 } 1386} 1387 1388void OMXCodec::fillOutputBuffer(BufferInfo *info) { 1389 CHECK_EQ(info->mOwnedByComponent, false); 1390 1391 if (mNoMoreOutputData) { 1392 LOGV("There is no more output data available, not " 1393 "calling fillOutputBuffer"); 1394 return; 1395 } 1396 1397 LOGV("Calling fill_buffer on buffer %p", info->mBuffer); 1398 mOMX->fill_buffer(mNode, info->mBuffer); 1399 1400 info->mOwnedByComponent = true; 1401} 1402 1403void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) { 1404 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput]; 1405 for (size_t i = 0; i < buffers->size(); ++i) { 1406 if ((*buffers)[i].mBuffer == buffer) { 1407 drainInputBuffer(&buffers->editItemAt(i)); 1408 return; 1409 } 1410 } 1411 1412 CHECK(!"should not be here."); 1413} 1414 1415void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) { 1416 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput]; 1417 for (size_t i = 0; i < buffers->size(); ++i) { 1418 if ((*buffers)[i].mBuffer == buffer) { 1419 fillOutputBuffer(&buffers->editItemAt(i)); 1420 return; 1421 } 1422 } 1423 1424 CHECK(!"should not be here."); 1425} 1426 1427void OMXCodec::setState(State newState) { 1428 mState = newState; 1429 mAsyncCompletion.signal(); 1430 1431 // This may cause some spurious wakeups but is necessary to 1432 // unblock the reader if we enter ERROR state. 1433 mBufferFilled.signal(); 1434} 1435 1436void OMXCodec::setAMRFormat() { 1437 if (!mIsEncoder) { 1438 OMX_AUDIO_PARAM_AMRTYPE def; 1439 def.nSize = sizeof(def); 1440 def.nVersion.s.nVersionMajor = 1; 1441 def.nVersion.s.nVersionMinor = 1; 1442 def.nPortIndex = kPortIndexInput; 1443 1444 status_t err = 1445 mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1446 1447 CHECK_EQ(err, OK); 1448 1449 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 1450 def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0; 1451 1452 err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1453 CHECK_EQ(err, OK); 1454 } 1455 1456 //////////////////////// 1457 1458 if (mIsEncoder) { 1459 sp<MetaData> format = mSource->getFormat(); 1460 int32_t sampleRate; 1461 int32_t numChannels; 1462 CHECK(format->findInt32(kKeySampleRate, &sampleRate)); 1463 CHECK(format->findInt32(kKeyChannelCount, &numChannels)); 1464 1465 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 1466 pcmParams.nSize = sizeof(pcmParams); 1467 pcmParams.nVersion.s.nVersionMajor = 1; 1468 pcmParams.nVersion.s.nVersionMinor = 1; 1469 pcmParams.nPortIndex = kPortIndexInput; 1470 1471 status_t err = mOMX->get_parameter( 1472 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1473 1474 CHECK_EQ(err, OK); 1475 1476 pcmParams.nChannels = numChannels; 1477 pcmParams.eNumData = OMX_NumericalDataSigned; 1478 pcmParams.bInterleaved = OMX_TRUE; 1479 pcmParams.nBitPerSample = 16; 1480 pcmParams.nSamplingRate = sampleRate; 1481 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 1482 1483 if (numChannels == 1) { 1484 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF; 1485 } else { 1486 CHECK_EQ(numChannels, 2); 1487 1488 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF; 1489 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF; 1490 } 1491 1492 err = mOMX->set_parameter( 1493 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1494 1495 CHECK_EQ(err, OK); 1496 } 1497} 1498 1499void OMXCodec::setAACFormat() { 1500 OMX_AUDIO_PARAM_AACPROFILETYPE def; 1501 def.nSize = sizeof(def); 1502 def.nVersion.s.nVersionMajor = 1; 1503 def.nVersion.s.nVersionMinor = 1; 1504 def.nPortIndex = kPortIndexInput; 1505 1506 status_t err = 1507 mOMX->get_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def)); 1508 CHECK_EQ(err, OK); 1509 1510 def.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 1511 1512 err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def)); 1513 CHECK_EQ(err, OK); 1514} 1515 1516void OMXCodec::setImageOutputFormat( 1517 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) { 1518 LOGV("setImageOutputFormat(%ld, %ld)", width, height); 1519 1520#if 0 1521 OMX_INDEXTYPE index; 1522 status_t err = mOMX->get_extension_index( 1523 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index); 1524 CHECK_EQ(err, OK); 1525 1526 err = mOMX->set_config(mNode, index, &format, sizeof(format)); 1527 CHECK_EQ(err, OK); 1528#endif 1529 1530 OMX_PARAM_PORTDEFINITIONTYPE def; 1531 def.nSize = sizeof(def); 1532 def.nVersion.s.nVersionMajor = 1; 1533 def.nVersion.s.nVersionMinor = 1; 1534 def.nPortIndex = kPortIndexOutput; 1535 1536 status_t err = mOMX->get_parameter( 1537 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1538 CHECK_EQ(err, OK); 1539 1540 CHECK_EQ(def.eDomain, OMX_PortDomainImage); 1541 1542 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; 1543 1544 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused); 1545 imageDef->eColorFormat = format; 1546 imageDef->nFrameWidth = width; 1547 imageDef->nFrameHeight = height; 1548 1549 switch (format) { 1550 case OMX_COLOR_FormatYUV420PackedPlanar: 1551 case OMX_COLOR_FormatYUV411Planar: 1552 { 1553 def.nBufferSize = (width * height * 3) / 2; 1554 break; 1555 } 1556 1557 case OMX_COLOR_FormatCbYCrY: 1558 { 1559 def.nBufferSize = width * height * 2; 1560 break; 1561 } 1562 1563 case OMX_COLOR_Format32bitARGB8888: 1564 { 1565 def.nBufferSize = width * height * 4; 1566 break; 1567 } 1568 1569 default: 1570 CHECK(!"Should not be here. Unknown color format."); 1571 break; 1572 } 1573 1574 def.nBufferCountActual = def.nBufferCountMin; 1575 1576 err = mOMX->set_parameter( 1577 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1578 CHECK_EQ(err, OK); 1579} 1580 1581void OMXCodec::setJPEGInputFormat( 1582 OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) { 1583 OMX_PARAM_PORTDEFINITIONTYPE def; 1584 def.nSize = sizeof(def); 1585 def.nVersion.s.nVersionMajor = 1; 1586 def.nVersion.s.nVersionMinor = 1; 1587 def.nPortIndex = kPortIndexInput; 1588 1589 status_t err = mOMX->get_parameter( 1590 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1591 CHECK_EQ(err, OK); 1592 1593 CHECK_EQ(def.eDomain, OMX_PortDomainImage); 1594 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; 1595 1596 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG); 1597 imageDef->nFrameWidth = width; 1598 imageDef->nFrameHeight = height; 1599 1600 def.nBufferSize = compressedSize; 1601 def.nBufferCountActual = def.nBufferCountMin; 1602 1603 err = mOMX->set_parameter( 1604 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1605 CHECK_EQ(err, OK); 1606} 1607 1608void OMXCodec::addCodecSpecificData(const void *data, size_t size) { 1609 CodecSpecificData *specific = 1610 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1); 1611 1612 specific->mSize = size; 1613 memcpy(specific->mData, data, size); 1614 1615 mCodecSpecificData.push(specific); 1616} 1617 1618void OMXCodec::clearCodecSpecificData() { 1619 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) { 1620 free(mCodecSpecificData.editItemAt(i)); 1621 } 1622 mCodecSpecificData.clear(); 1623 mCodecSpecificDataIndex = 0; 1624} 1625 1626status_t OMXCodec::start(MetaData *) { 1627 Mutex::Autolock autoLock(mLock); 1628 1629 if (mState != LOADED) { 1630 return UNKNOWN_ERROR; 1631 } 1632 1633 sp<MetaData> params = new MetaData; 1634 if (mQuirks & kWantsNALFragments) { 1635 params->setInt32(kKeyWantsNALFragments, true); 1636 } 1637 status_t err = mSource->start(params.get()); 1638 1639 if (err != OK) { 1640 return err; 1641 } 1642 1643 mCodecSpecificDataIndex = 0; 1644 mInitialBufferSubmit = true; 1645 mSignalledEOS = false; 1646 mNoMoreOutputData = false; 1647 mSeekTimeUs = -1; 1648 mFilledBuffers.clear(); 1649 1650 return init(); 1651} 1652 1653status_t OMXCodec::stop() { 1654 LOGV("stop"); 1655 1656 Mutex::Autolock autoLock(mLock); 1657 1658 while (isIntermediateState(mState)) { 1659 mAsyncCompletion.wait(mLock); 1660 } 1661 1662 switch (mState) { 1663 case LOADED: 1664 case ERROR: 1665 break; 1666 1667 case EXECUTING: 1668 { 1669 setState(EXECUTING_TO_IDLE); 1670 1671 if (mQuirks & kRequiresFlushBeforeShutdown) { 1672 LOGV("This component requires a flush before transitioning " 1673 "from EXECUTING to IDLE..."); 1674 1675 bool emulateInputFlushCompletion = 1676 !flushPortAsync(kPortIndexInput); 1677 1678 bool emulateOutputFlushCompletion = 1679 !flushPortAsync(kPortIndexOutput); 1680 1681 if (emulateInputFlushCompletion) { 1682 onCmdComplete(OMX_CommandFlush, kPortIndexInput); 1683 } 1684 1685 if (emulateOutputFlushCompletion) { 1686 onCmdComplete(OMX_CommandFlush, kPortIndexOutput); 1687 } 1688 } else { 1689 mPortStatus[kPortIndexInput] = SHUTTING_DOWN; 1690 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN; 1691 1692 status_t err = 1693 mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle); 1694 CHECK_EQ(err, OK); 1695 } 1696 1697 while (mState != LOADED && mState != ERROR) { 1698 mAsyncCompletion.wait(mLock); 1699 } 1700 1701 break; 1702 } 1703 1704 default: 1705 { 1706 CHECK(!"should not be here."); 1707 break; 1708 } 1709 } 1710 1711 mSource->stop(); 1712 1713 return OK; 1714} 1715 1716sp<MetaData> OMXCodec::getFormat() { 1717 return mOutputFormat; 1718} 1719 1720status_t OMXCodec::read( 1721 MediaBuffer **buffer, const ReadOptions *options) { 1722 *buffer = NULL; 1723 1724 Mutex::Autolock autoLock(mLock); 1725 1726 if (mState != EXECUTING && mState != RECONFIGURING) { 1727 return UNKNOWN_ERROR; 1728 } 1729 1730 if (mInitialBufferSubmit) { 1731 mInitialBufferSubmit = false; 1732 1733 drainInputBuffers(); 1734 1735 if (mState == EXECUTING) { 1736 // Otherwise mState == RECONFIGURING and this code will trigger 1737 // after the output port is reenabled. 1738 fillOutputBuffers(); 1739 } 1740 } 1741 1742 int64_t seekTimeUs; 1743 if (options && options->getSeekTo(&seekTimeUs)) { 1744 LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6); 1745 1746 mSignalledEOS = false; 1747 mNoMoreOutputData = false; 1748 1749 CHECK(seekTimeUs >= 0); 1750 mSeekTimeUs = seekTimeUs; 1751 1752 mFilledBuffers.clear(); 1753 1754 CHECK_EQ(mState, EXECUTING); 1755 1756 bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput); 1757 bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput); 1758 1759 if (emulateInputFlushCompletion) { 1760 onCmdComplete(OMX_CommandFlush, kPortIndexInput); 1761 } 1762 1763 if (emulateOutputFlushCompletion) { 1764 onCmdComplete(OMX_CommandFlush, kPortIndexOutput); 1765 } 1766 } 1767 1768 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) { 1769 mBufferFilled.wait(mLock); 1770 } 1771 1772 if (mState == ERROR) { 1773 return UNKNOWN_ERROR; 1774 } 1775 1776 if (mFilledBuffers.empty()) { 1777 return ERROR_END_OF_STREAM; 1778 } 1779 1780 size_t index = *mFilledBuffers.begin(); 1781 mFilledBuffers.erase(mFilledBuffers.begin()); 1782 1783 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 1784 info->mMediaBuffer->add_ref(); 1785 *buffer = info->mMediaBuffer; 1786 1787 return OK; 1788} 1789 1790void OMXCodec::signalBufferReturned(MediaBuffer *buffer) { 1791 Mutex::Autolock autoLock(mLock); 1792 1793 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput]; 1794 for (size_t i = 0; i < buffers->size(); ++i) { 1795 BufferInfo *info = &buffers->editItemAt(i); 1796 1797 if (info->mMediaBuffer == buffer) { 1798 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED); 1799 fillOutputBuffer(info); 1800 return; 1801 } 1802 } 1803 1804 CHECK(!"should not be here."); 1805} 1806 1807static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) { 1808 static const char *kNames[] = { 1809 "OMX_IMAGE_CodingUnused", 1810 "OMX_IMAGE_CodingAutoDetect", 1811 "OMX_IMAGE_CodingJPEG", 1812 "OMX_IMAGE_CodingJPEG2K", 1813 "OMX_IMAGE_CodingEXIF", 1814 "OMX_IMAGE_CodingTIFF", 1815 "OMX_IMAGE_CodingGIF", 1816 "OMX_IMAGE_CodingPNG", 1817 "OMX_IMAGE_CodingLZW", 1818 "OMX_IMAGE_CodingBMP", 1819 }; 1820 1821 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 1822 1823 if (type < 0 || (size_t)type >= numNames) { 1824 return "UNKNOWN"; 1825 } else { 1826 return kNames[type]; 1827 } 1828} 1829 1830static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) { 1831 static const char *kNames[] = { 1832 "OMX_COLOR_FormatUnused", 1833 "OMX_COLOR_FormatMonochrome", 1834 "OMX_COLOR_Format8bitRGB332", 1835 "OMX_COLOR_Format12bitRGB444", 1836 "OMX_COLOR_Format16bitARGB4444", 1837 "OMX_COLOR_Format16bitARGB1555", 1838 "OMX_COLOR_Format16bitRGB565", 1839 "OMX_COLOR_Format16bitBGR565", 1840 "OMX_COLOR_Format18bitRGB666", 1841 "OMX_COLOR_Format18bitARGB1665", 1842 "OMX_COLOR_Format19bitARGB1666", 1843 "OMX_COLOR_Format24bitRGB888", 1844 "OMX_COLOR_Format24bitBGR888", 1845 "OMX_COLOR_Format24bitARGB1887", 1846 "OMX_COLOR_Format25bitARGB1888", 1847 "OMX_COLOR_Format32bitBGRA8888", 1848 "OMX_COLOR_Format32bitARGB8888", 1849 "OMX_COLOR_FormatYUV411Planar", 1850 "OMX_COLOR_FormatYUV411PackedPlanar", 1851 "OMX_COLOR_FormatYUV420Planar", 1852 "OMX_COLOR_FormatYUV420PackedPlanar", 1853 "OMX_COLOR_FormatYUV420SemiPlanar", 1854 "OMX_COLOR_FormatYUV422Planar", 1855 "OMX_COLOR_FormatYUV422PackedPlanar", 1856 "OMX_COLOR_FormatYUV422SemiPlanar", 1857 "OMX_COLOR_FormatYCbYCr", 1858 "OMX_COLOR_FormatYCrYCb", 1859 "OMX_COLOR_FormatCbYCrY", 1860 "OMX_COLOR_FormatCrYCbY", 1861 "OMX_COLOR_FormatYUV444Interleaved", 1862 "OMX_COLOR_FormatRawBayer8bit", 1863 "OMX_COLOR_FormatRawBayer10bit", 1864 "OMX_COLOR_FormatRawBayer8bitcompressed", 1865 "OMX_COLOR_FormatL2", 1866 "OMX_COLOR_FormatL4", 1867 "OMX_COLOR_FormatL8", 1868 "OMX_COLOR_FormatL16", 1869 "OMX_COLOR_FormatL24", 1870 "OMX_COLOR_FormatL32", 1871 "OMX_COLOR_FormatYUV420PackedSemiPlanar", 1872 "OMX_COLOR_FormatYUV422PackedSemiPlanar", 1873 "OMX_COLOR_Format18BitBGR666", 1874 "OMX_COLOR_Format24BitARGB6666", 1875 "OMX_COLOR_Format24BitABGR6666", 1876 }; 1877 1878 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 1879 1880 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; 1881 1882 if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) { 1883 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar"; 1884 } else if (type < 0 || (size_t)type >= numNames) { 1885 return "UNKNOWN"; 1886 } else { 1887 return kNames[type]; 1888 } 1889} 1890 1891static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) { 1892 static const char *kNames[] = { 1893 "OMX_VIDEO_CodingUnused", 1894 "OMX_VIDEO_CodingAutoDetect", 1895 "OMX_VIDEO_CodingMPEG2", 1896 "OMX_VIDEO_CodingH263", 1897 "OMX_VIDEO_CodingMPEG4", 1898 "OMX_VIDEO_CodingWMV", 1899 "OMX_VIDEO_CodingRV", 1900 "OMX_VIDEO_CodingAVC", 1901 "OMX_VIDEO_CodingMJPEG", 1902 }; 1903 1904 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 1905 1906 if (type < 0 || (size_t)type >= numNames) { 1907 return "UNKNOWN"; 1908 } else { 1909 return kNames[type]; 1910 } 1911} 1912 1913static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) { 1914 static const char *kNames[] = { 1915 "OMX_AUDIO_CodingUnused", 1916 "OMX_AUDIO_CodingAutoDetect", 1917 "OMX_AUDIO_CodingPCM", 1918 "OMX_AUDIO_CodingADPCM", 1919 "OMX_AUDIO_CodingAMR", 1920 "OMX_AUDIO_CodingGSMFR", 1921 "OMX_AUDIO_CodingGSMEFR", 1922 "OMX_AUDIO_CodingGSMHR", 1923 "OMX_AUDIO_CodingPDCFR", 1924 "OMX_AUDIO_CodingPDCEFR", 1925 "OMX_AUDIO_CodingPDCHR", 1926 "OMX_AUDIO_CodingTDMAFR", 1927 "OMX_AUDIO_CodingTDMAEFR", 1928 "OMX_AUDIO_CodingQCELP8", 1929 "OMX_AUDIO_CodingQCELP13", 1930 "OMX_AUDIO_CodingEVRC", 1931 "OMX_AUDIO_CodingSMV", 1932 "OMX_AUDIO_CodingG711", 1933 "OMX_AUDIO_CodingG723", 1934 "OMX_AUDIO_CodingG726", 1935 "OMX_AUDIO_CodingG729", 1936 "OMX_AUDIO_CodingAAC", 1937 "OMX_AUDIO_CodingMP3", 1938 "OMX_AUDIO_CodingSBC", 1939 "OMX_AUDIO_CodingVORBIS", 1940 "OMX_AUDIO_CodingWMA", 1941 "OMX_AUDIO_CodingRA", 1942 "OMX_AUDIO_CodingMIDI", 1943 }; 1944 1945 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 1946 1947 if (type < 0 || (size_t)type >= numNames) { 1948 return "UNKNOWN"; 1949 } else { 1950 return kNames[type]; 1951 } 1952} 1953 1954static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) { 1955 static const char *kNames[] = { 1956 "OMX_AUDIO_PCMModeLinear", 1957 "OMX_AUDIO_PCMModeALaw", 1958 "OMX_AUDIO_PCMModeMULaw", 1959 }; 1960 1961 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 1962 1963 if (type < 0 || (size_t)type >= numNames) { 1964 return "UNKNOWN"; 1965 } else { 1966 return kNames[type]; 1967 } 1968} 1969 1970 1971void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { 1972 OMX_PARAM_PORTDEFINITIONTYPE def; 1973 def.nSize = sizeof(def); 1974 def.nVersion.s.nVersionMajor = 1; 1975 def.nVersion.s.nVersionMinor = 1; 1976 def.nPortIndex = portIndex; 1977 1978 status_t err = mOMX->get_parameter( 1979 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1980 CHECK_EQ(err, OK); 1981 1982 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output"); 1983 1984 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput) 1985 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput)); 1986 1987 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual); 1988 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin); 1989 printf(" nBufferSize = %ld\n", def.nBufferSize); 1990 1991 switch (def.eDomain) { 1992 case OMX_PortDomainImage: 1993 { 1994 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; 1995 1996 printf("\n"); 1997 printf(" // Image\n"); 1998 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth); 1999 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight); 2000 printf(" nStride = %ld\n", imageDef->nStride); 2001 2002 printf(" eCompressionFormat = %s\n", 2003 imageCompressionFormatString(imageDef->eCompressionFormat)); 2004 2005 printf(" eColorFormat = %s\n", 2006 colorFormatString(imageDef->eColorFormat)); 2007 2008 break; 2009 } 2010 2011 case OMX_PortDomainVideo: 2012 { 2013 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 2014 2015 printf("\n"); 2016 printf(" // Video\n"); 2017 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth); 2018 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight); 2019 printf(" nStride = %ld\n", videoDef->nStride); 2020 2021 printf(" eCompressionFormat = %s\n", 2022 videoCompressionFormatString(videoDef->eCompressionFormat)); 2023 2024 printf(" eColorFormat = %s\n", 2025 colorFormatString(videoDef->eColorFormat)); 2026 2027 break; 2028 } 2029 2030 case OMX_PortDomainAudio: 2031 { 2032 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 2033 2034 printf("\n"); 2035 printf(" // Audio\n"); 2036 printf(" eEncoding = %s\n", 2037 audioCodingTypeString(audioDef->eEncoding)); 2038 2039 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) { 2040 OMX_AUDIO_PARAM_PCMMODETYPE params; 2041 params.nSize = sizeof(params); 2042 params.nVersion.s.nVersionMajor = 1; 2043 params.nVersion.s.nVersionMinor = 1; 2044 params.nPortIndex = portIndex; 2045 2046 err = mOMX->get_parameter( 2047 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 2048 CHECK_EQ(err, OK); 2049 2050 printf(" nSamplingRate = %ld\n", params.nSamplingRate); 2051 printf(" nChannels = %ld\n", params.nChannels); 2052 printf(" bInterleaved = %d\n", params.bInterleaved); 2053 printf(" nBitPerSample = %ld\n", params.nBitPerSample); 2054 2055 printf(" eNumData = %s\n", 2056 params.eNumData == OMX_NumericalDataSigned 2057 ? "signed" : "unsigned"); 2058 2059 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode)); 2060 } 2061 2062 break; 2063 } 2064 2065 default: 2066 { 2067 printf(" // Unknown\n"); 2068 break; 2069 } 2070 } 2071 2072 printf("}\n"); 2073} 2074 2075void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { 2076 mOutputFormat = new MetaData; 2077 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName); 2078 2079 OMX_PARAM_PORTDEFINITIONTYPE def; 2080 def.nSize = sizeof(def); 2081 def.nVersion.s.nVersionMajor = 1; 2082 def.nVersion.s.nVersionMinor = 1; 2083 def.nPortIndex = kPortIndexOutput; 2084 2085 status_t err = mOMX->get_parameter( 2086 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2087 CHECK_EQ(err, OK); 2088 2089 switch (def.eDomain) { 2090 case OMX_PortDomainImage: 2091 { 2092 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; 2093 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused); 2094 2095 mOutputFormat->setCString(kKeyMIMEType, "image/raw"); 2096 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat); 2097 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth); 2098 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight); 2099 break; 2100 } 2101 2102 case OMX_PortDomainAudio: 2103 { 2104 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio; 2105 2106 CHECK_EQ(audio_def->eEncoding, OMX_AUDIO_CodingPCM); 2107 2108 OMX_AUDIO_PARAM_PCMMODETYPE params; 2109 params.nSize = sizeof(params); 2110 params.nVersion.s.nVersionMajor = 1; 2111 params.nVersion.s.nVersionMinor = 1; 2112 params.nPortIndex = kPortIndexOutput; 2113 2114 err = mOMX->get_parameter( 2115 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 2116 CHECK_EQ(err, OK); 2117 2118 CHECK_EQ(params.eNumData, OMX_NumericalDataSigned); 2119 CHECK_EQ(params.nBitPerSample, 16); 2120 CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear); 2121 2122 int32_t numChannels, sampleRate; 2123 inputFormat->findInt32(kKeyChannelCount, &numChannels); 2124 inputFormat->findInt32(kKeySampleRate, &sampleRate); 2125 2126 mOutputFormat->setCString(kKeyMIMEType, "audio/raw"); 2127 mOutputFormat->setInt32(kKeyChannelCount, numChannels); 2128 mOutputFormat->setInt32(kKeySampleRate, sampleRate); 2129 break; 2130 } 2131 2132 case OMX_PortDomainVideo: 2133 { 2134 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2135 2136 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) { 2137 mOutputFormat->setCString(kKeyMIMEType, "video/raw"); 2138 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) { 2139 mOutputFormat->setCString(kKeyMIMEType, "video/mp4v-es"); 2140 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) { 2141 mOutputFormat->setCString(kKeyMIMEType, "video/3gpp"); 2142 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) { 2143 mOutputFormat->setCString(kKeyMIMEType, "video/avc"); 2144 } else { 2145 CHECK(!"Unknown compression format."); 2146 } 2147 2148 if (!strcmp(mComponentName, "OMX.PV.avcdec")) { 2149 // This component appears to be lying to me. 2150 mOutputFormat->setInt32( 2151 kKeyWidth, (video_def->nFrameWidth + 15) & -16); 2152 mOutputFormat->setInt32( 2153 kKeyHeight, (video_def->nFrameHeight + 15) & -16); 2154 } else { 2155 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth); 2156 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight); 2157 } 2158 2159 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat); 2160 break; 2161 } 2162 2163 default: 2164 { 2165 CHECK(!"should not be here, neither audio nor video."); 2166 break; 2167 } 2168 } 2169} 2170 2171} // namespace android 2172