OMXCodec.cpp revision b1ccb623d9db42c451aa9dd4e8cf0e76b164aa50
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 "include/AACDecoder.h" 22#include "include/AMRNBDecoder.h" 23#include "include/AMRNBEncoder.h" 24#include "include/AMRWBDecoder.h" 25#include "include/AVCDecoder.h" 26#include "include/M4vH263Decoder.h" 27#include "include/MP3Decoder.h" 28#include "include/VorbisDecoder.h" 29 30#include "include/ESDS.h" 31 32#include <binder/IServiceManager.h> 33#include <binder/MemoryDealer.h> 34#include <binder/ProcessState.h> 35#include <media/IMediaPlayerService.h> 36#include <media/stagefright/MediaBuffer.h> 37#include <media/stagefright/MediaBufferGroup.h> 38#include <media/stagefright/MediaDebug.h> 39#include <media/stagefright/MediaDefs.h> 40#include <media/stagefright/MediaExtractor.h> 41#include <media/stagefright/MetaData.h> 42#include <media/stagefright/OMXCodec.h> 43#include <media/stagefright/Utils.h> 44#include <utils/Vector.h> 45 46#include <OMX_Audio.h> 47#include <OMX_Component.h> 48 49namespace android { 50 51static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; 52 53struct CodecInfo { 54 const char *mime; 55 const char *codec; 56}; 57 58#define FACTORY_CREATE(name) \ 59static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \ 60 return new name(source); \ 61} 62 63#define FACTORY_REF(name) { #name, Make##name }, 64 65FACTORY_CREATE(MP3Decoder) 66FACTORY_CREATE(AMRNBDecoder) 67FACTORY_CREATE(AMRWBDecoder) 68FACTORY_CREATE(AACDecoder) 69FACTORY_CREATE(AVCDecoder) 70FACTORY_CREATE(M4vH263Decoder) 71FACTORY_CREATE(VorbisDecoder) 72FACTORY_CREATE(AMRNBEncoder) 73 74static sp<MediaSource> InstantiateSoftwareCodec( 75 const char *name, const sp<MediaSource> &source) { 76 struct FactoryInfo { 77 const char *name; 78 sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &); 79 }; 80 81 static const FactoryInfo kFactoryInfo[] = { 82 FACTORY_REF(MP3Decoder) 83 FACTORY_REF(AMRNBDecoder) 84 FACTORY_REF(AMRWBDecoder) 85 FACTORY_REF(AACDecoder) 86 FACTORY_REF(AVCDecoder) 87 FACTORY_REF(M4vH263Decoder) 88 FACTORY_REF(VorbisDecoder) 89 FACTORY_REF(AMRNBEncoder) 90 }; 91 for (size_t i = 0; 92 i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) { 93 if (!strcmp(name, kFactoryInfo[i].name)) { 94 return (*kFactoryInfo[i].CreateFunc)(source); 95 } 96 } 97 98 return NULL; 99} 100 101#undef FACTORY_REF 102#undef FACTORY_CREATE 103 104static const CodecInfo kDecoderInfo[] = { 105 { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" }, 106// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" }, 107 { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" }, 108// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.PV.mp3dec" }, 109// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" }, 110 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" }, 111// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrdec" }, 112 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" }, 113 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" }, 114// { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.PV.amrdec" }, 115 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" }, 116 { MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" }, 117// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacdec" }, 118 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" }, 119 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" }, 120 { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" }, 121// { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4dec" }, 122 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" }, 123 { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" }, 124// { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263dec" }, 125 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" }, 126 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" }, 127 { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" }, 128// { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcdec" }, 129 { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" }, 130}; 131 132static const CodecInfo kEncoderInfo[] = { 133 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" }, 134 { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" }, 135 { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" }, 136 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" }, 137 { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" }, 138 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" }, 139 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" }, 140 { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4enc" }, 141 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" }, 142 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" }, 143 { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" }, 144 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" }, 145 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" }, 146 { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" }, 147}; 148 149#undef OPTIONAL 150 151#define CODEC_LOGI(x, ...) LOGI("[%s] "x, mComponentName, ##__VA_ARGS__) 152#define CODEC_LOGV(x, ...) LOGV("[%s] "x, mComponentName, ##__VA_ARGS__) 153#define CODEC_LOGE(x, ...) LOGE("[%s] "x, mComponentName, ##__VA_ARGS__) 154 155struct OMXCodecObserver : public BnOMXObserver { 156 OMXCodecObserver() { 157 } 158 159 void setCodec(const sp<OMXCodec> &target) { 160 mTarget = target; 161 } 162 163 // from IOMXObserver 164 virtual void onMessage(const omx_message &msg) { 165 sp<OMXCodec> codec = mTarget.promote(); 166 167 if (codec.get() != NULL) { 168 codec->on_message(msg); 169 } 170 } 171 172protected: 173 virtual ~OMXCodecObserver() {} 174 175private: 176 wp<OMXCodec> mTarget; 177 178 OMXCodecObserver(const OMXCodecObserver &); 179 OMXCodecObserver &operator=(const OMXCodecObserver &); 180}; 181 182static const char *GetCodec(const CodecInfo *info, size_t numInfos, 183 const char *mime, int index) { 184 CHECK(index >= 0); 185 for(size_t i = 0; i < numInfos; ++i) { 186 if (!strcasecmp(mime, info[i].mime)) { 187 if (index == 0) { 188 return info[i].codec; 189 } 190 191 --index; 192 } 193 } 194 195 return NULL; 196} 197 198enum { 199 kAVCProfileBaseline = 0x42, 200 kAVCProfileMain = 0x4d, 201 kAVCProfileExtended = 0x58, 202 kAVCProfileHigh = 0x64, 203 kAVCProfileHigh10 = 0x6e, 204 kAVCProfileHigh422 = 0x7a, 205 kAVCProfileHigh444 = 0xf4, 206 kAVCProfileCAVLC444Intra = 0x2c 207}; 208 209static const char *AVCProfileToString(uint8_t profile) { 210 switch (profile) { 211 case kAVCProfileBaseline: 212 return "Baseline"; 213 case kAVCProfileMain: 214 return "Main"; 215 case kAVCProfileExtended: 216 return "Extended"; 217 case kAVCProfileHigh: 218 return "High"; 219 case kAVCProfileHigh10: 220 return "High 10"; 221 case kAVCProfileHigh422: 222 return "High 422"; 223 case kAVCProfileHigh444: 224 return "High 444"; 225 case kAVCProfileCAVLC444Intra: 226 return "CAVLC 444 Intra"; 227 default: return "Unknown"; 228 } 229} 230 231template<class T> 232static void InitOMXParams(T *params) { 233 params->nSize = sizeof(T); 234 params->nVersion.s.nVersionMajor = 1; 235 params->nVersion.s.nVersionMinor = 0; 236 params->nVersion.s.nRevision = 0; 237 params->nVersion.s.nStep = 0; 238} 239 240static bool IsSoftwareCodec(const char *componentName) { 241 if (!strncmp("OMX.PV.", componentName, 7)) { 242 return true; 243 } 244 245 return false; 246} 247 248// A sort order in which non-OMX components are first, 249// followed by software codecs, i.e. OMX.PV.*, followed 250// by all the others. 251static int CompareSoftwareCodecsFirst( 252 const String8 *elem1, const String8 *elem2) { 253 bool isNotOMX1 = strncmp(elem1->string(), "OMX.", 4); 254 bool isNotOMX2 = strncmp(elem2->string(), "OMX.", 4); 255 256 if (isNotOMX1) { 257 if (isNotOMX2) { return 0; } 258 return -1; 259 } 260 if (isNotOMX2) { 261 return 1; 262 } 263 264 bool isSoftwareCodec1 = IsSoftwareCodec(elem1->string()); 265 bool isSoftwareCodec2 = IsSoftwareCodec(elem2->string()); 266 267 if (isSoftwareCodec1) { 268 if (isSoftwareCodec2) { return 0; } 269 return -1; 270 } 271 272 if (isSoftwareCodec2) { 273 return 1; 274 } 275 276 return 0; 277} 278 279// static 280uint32_t OMXCodec::getComponentQuirks(const char *componentName) { 281 uint32_t quirks = 0; 282 283 if (!strcmp(componentName, "OMX.PV.avcdec")) { 284 quirks |= kWantsNALFragments; 285 } 286 if (!strcmp(componentName, "OMX.TI.MP3.decode")) { 287 quirks |= kNeedsFlushBeforeDisable; 288 quirks |= kDecoderLiesAboutNumberOfChannels; 289 } 290 if (!strcmp(componentName, "OMX.TI.AAC.decode")) { 291 quirks |= kNeedsFlushBeforeDisable; 292 quirks |= kRequiresFlushCompleteEmulation; 293 quirks |= kSupportsMultipleFramesPerInputBuffer; 294 } 295 if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) { 296 quirks |= kRequiresLoadedToIdleAfterAllocation; 297 quirks |= kRequiresAllocateBufferOnInputPorts; 298 quirks |= kRequiresAllocateBufferOnOutputPorts; 299 } 300 if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) { 301 quirks |= kRequiresAllocateBufferOnOutputPorts; 302 quirks |= kDefersOutputBufferAllocation; 303 } 304 305 if (!strncmp(componentName, "OMX.TI.", 7)) { 306 // Apparently I must not use OMX_UseBuffer on either input or 307 // output ports on any of the TI components or quote: 308 // "(I) may have unexpected problem (sic) which can be timing related 309 // and hard to reproduce." 310 311 quirks |= kRequiresAllocateBufferOnInputPorts; 312 quirks |= kRequiresAllocateBufferOnOutputPorts; 313 } 314 315 if (!strcmp(componentName, "OMX.TI.Video.Decoder")) { 316 quirks |= kInputBufferSizesAreBogus; 317 } 318 319 return quirks; 320} 321 322// static 323void OMXCodec::findMatchingCodecs( 324 const char *mime, 325 bool createEncoder, const char *matchComponentName, 326 uint32_t flags, 327 Vector<String8> *matchingCodecs) { 328 matchingCodecs->clear(); 329 330 for (int index = 0;; ++index) { 331 const char *componentName; 332 333 if (createEncoder) { 334 componentName = GetCodec( 335 kEncoderInfo, 336 sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]), 337 mime, index); 338 } else { 339 componentName = GetCodec( 340 kDecoderInfo, 341 sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]), 342 mime, index); 343 } 344 345 if (!componentName) { 346 break; 347 } 348 349 // If a specific codec is requested, skip the non-matching ones. 350 if (matchComponentName && strcmp(componentName, matchComponentName)) { 351 continue; 352 } 353 354 matchingCodecs->push(String8(componentName)); 355 } 356 357 if (flags & kPreferSoftwareCodecs) { 358 matchingCodecs->sort(CompareSoftwareCodecsFirst); 359 } 360} 361 362// static 363sp<MediaSource> OMXCodec::Create( 364 const sp<IOMX> &omx, 365 const sp<MetaData> &meta, bool createEncoder, 366 const sp<MediaSource> &source, 367 const char *matchComponentName, 368 uint32_t flags) { 369 const char *mime; 370 bool success = meta->findCString(kKeyMIMEType, &mime); 371 CHECK(success); 372 373 Vector<String8> matchingCodecs; 374 findMatchingCodecs( 375 mime, createEncoder, matchComponentName, flags, &matchingCodecs); 376 377 if (matchingCodecs.isEmpty()) { 378 return NULL; 379 } 380 381 sp<OMXCodecObserver> observer = new OMXCodecObserver; 382 IOMX::node_id node = 0; 383 384 const char *componentName; 385 for (size_t i = 0; i < matchingCodecs.size(); ++i) { 386 componentName = matchingCodecs[i].string(); 387 388#if BUILD_WITH_FULL_STAGEFRIGHT 389 sp<MediaSource> softwareCodec = 390 InstantiateSoftwareCodec(componentName, source); 391 392 if (softwareCodec != NULL) { 393 LOGV("Successfully allocated software codec '%s'", componentName); 394 395 return softwareCodec; 396 } 397#endif 398 399 LOGV("Attempting to allocate OMX node '%s'", componentName); 400 401 status_t err = omx->allocateNode(componentName, observer, &node); 402 if (err == OK) { 403 LOGV("Successfully allocated OMX node '%s'", componentName); 404 405 sp<OMXCodec> codec = new OMXCodec( 406 omx, node, getComponentQuirks(componentName), 407 createEncoder, mime, componentName, 408 source); 409 410 observer->setCodec(codec); 411 412 err = codec->configureCodec(meta); 413 414 if (err == OK) { 415 return codec; 416 } 417 418 LOGV("Failed to configure codec '%s'", componentName); 419 } 420 } 421 422 return NULL; 423} 424 425status_t OMXCodec::configureCodec(const sp<MetaData> &meta) { 426 uint32_t type; 427 const void *data; 428 size_t size; 429 if (meta->findData(kKeyESDS, &type, &data, &size)) { 430 ESDS esds((const char *)data, size); 431 CHECK_EQ(esds.InitCheck(), OK); 432 433 const void *codec_specific_data; 434 size_t codec_specific_data_size; 435 esds.getCodecSpecificInfo( 436 &codec_specific_data, &codec_specific_data_size); 437 438 addCodecSpecificData( 439 codec_specific_data, codec_specific_data_size); 440 } else if (meta->findData(kKeyAVCC, &type, &data, &size)) { 441 // Parse the AVCDecoderConfigurationRecord 442 443 const uint8_t *ptr = (const uint8_t *)data; 444 445 CHECK(size >= 7); 446 CHECK_EQ(ptr[0], 1); // configurationVersion == 1 447 uint8_t profile = ptr[1]; 448 uint8_t level = ptr[3]; 449 450 // There is decodable content out there that fails the following 451 // assertion, let's be lenient for now... 452 // CHECK((ptr[4] >> 2) == 0x3f); // reserved 453 454 size_t lengthSize = 1 + (ptr[4] & 3); 455 456 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp 457 // violates it... 458 // CHECK((ptr[5] >> 5) == 7); // reserved 459 460 size_t numSeqParameterSets = ptr[5] & 31; 461 462 ptr += 6; 463 size -= 6; 464 465 for (size_t i = 0; i < numSeqParameterSets; ++i) { 466 CHECK(size >= 2); 467 size_t length = U16_AT(ptr); 468 469 ptr += 2; 470 size -= 2; 471 472 CHECK(size >= length); 473 474 addCodecSpecificData(ptr, length); 475 476 ptr += length; 477 size -= length; 478 } 479 480 CHECK(size >= 1); 481 size_t numPictureParameterSets = *ptr; 482 ++ptr; 483 --size; 484 485 for (size_t i = 0; i < numPictureParameterSets; ++i) { 486 CHECK(size >= 2); 487 size_t length = U16_AT(ptr); 488 489 ptr += 2; 490 size -= 2; 491 492 CHECK(size >= length); 493 494 addCodecSpecificData(ptr, length); 495 496 ptr += length; 497 size -= length; 498 } 499 500 LOGV("AVC profile = %d (%s), level = %d", 501 (int)profile, AVCProfileToString(profile), (int)level / 10); 502 503 if (!strcmp(mComponentName, "OMX.TI.Video.Decoder") 504 && (profile != kAVCProfileBaseline || level > 39)) { 505 // This stream exceeds the decoder's capabilities. The decoder 506 // does not handle this gracefully and would clobber the heap 507 // and wreak havoc instead... 508 509 LOGE("Profile and/or level exceed the decoder's capabilities."); 510 return ERROR_UNSUPPORTED; 511 } 512 } 513 514 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) { 515 setAMRFormat(false /* isWAMR */); 516 } 517 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) { 518 setAMRFormat(true /* isWAMR */); 519 } 520 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) { 521 int32_t numChannels, sampleRate; 522 CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); 523 CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); 524 525 setAACFormat(numChannels, sampleRate); 526 } 527 528 if (!strncasecmp(mMIME, "video/", 6)) { 529 int32_t width, height; 530 bool success = meta->findInt32(kKeyWidth, &width); 531 success = success && meta->findInt32(kKeyHeight, &height); 532 CHECK(success); 533 534 if (mIsEncoder) { 535 setVideoInputFormat(mMIME, width, height); 536 } else { 537 status_t err = setVideoOutputFormat( 538 mMIME, width, height); 539 540 if (err != OK) { 541 return err; 542 } 543 } 544 } 545 546 if (!strcasecmp(mMIME, MEDIA_MIMETYPE_IMAGE_JPEG) 547 && !strcmp(mComponentName, "OMX.TI.JPEG.decode")) { 548 OMX_COLOR_FORMATTYPE format = 549 OMX_COLOR_Format32bitARGB8888; 550 // OMX_COLOR_FormatYUV420PackedPlanar; 551 // OMX_COLOR_FormatCbYCrY; 552 // OMX_COLOR_FormatYUV411Planar; 553 554 int32_t width, height; 555 bool success = meta->findInt32(kKeyWidth, &width); 556 success = success && meta->findInt32(kKeyHeight, &height); 557 558 int32_t compressedSize; 559 success = success && meta->findInt32( 560 kKeyMaxInputSize, &compressedSize); 561 562 CHECK(success); 563 CHECK(compressedSize > 0); 564 565 setImageOutputFormat(format, width, height); 566 setJPEGInputFormat(width, height, (OMX_U32)compressedSize); 567 } 568 569 int32_t maxInputSize; 570 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) { 571 setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize); 572 } 573 574 if (!strcmp(mComponentName, "OMX.TI.AMR.encode") 575 || !strcmp(mComponentName, "OMX.TI.WBAMR.encode") 576 || !strcmp(mComponentName, "OMX.TI.AAC.encode")) { 577 setMinBufferSize(kPortIndexOutput, 8192); // XXX 578 } 579 580 initOutputFormat(meta); 581 582 return OK; 583} 584 585void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) { 586 OMX_PARAM_PORTDEFINITIONTYPE def; 587 InitOMXParams(&def); 588 def.nPortIndex = portIndex; 589 590 status_t err = mOMX->getParameter( 591 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 592 CHECK_EQ(err, OK); 593 594 if ((portIndex == kPortIndexInput && (mQuirks & kInputBufferSizesAreBogus)) 595 || (def.nBufferSize < size)) { 596 def.nBufferSize = size; 597 } 598 599 err = mOMX->setParameter( 600 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 601 CHECK_EQ(err, OK); 602 603 err = mOMX->getParameter( 604 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 605 CHECK_EQ(err, OK); 606 607 // Make sure the setting actually stuck. 608 if (portIndex == kPortIndexInput 609 && (mQuirks & kInputBufferSizesAreBogus)) { 610 CHECK_EQ(def.nBufferSize, size); 611 } else { 612 CHECK(def.nBufferSize >= size); 613 } 614} 615 616status_t OMXCodec::setVideoPortFormatType( 617 OMX_U32 portIndex, 618 OMX_VIDEO_CODINGTYPE compressionFormat, 619 OMX_COLOR_FORMATTYPE colorFormat) { 620 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 621 InitOMXParams(&format); 622 format.nPortIndex = portIndex; 623 format.nIndex = 0; 624 bool found = false; 625 626 OMX_U32 index = 0; 627 for (;;) { 628 format.nIndex = index; 629 status_t err = mOMX->getParameter( 630 mNode, OMX_IndexParamVideoPortFormat, 631 &format, sizeof(format)); 632 633 if (err != OK) { 634 return err; 635 } 636 637 // The following assertion is violated by TI's video decoder. 638 // CHECK_EQ(format.nIndex, index); 639 640#if 1 641 CODEC_LOGV("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d", 642 portIndex, 643 index, format.eCompressionFormat, format.eColorFormat); 644#endif 645 646 if (!strcmp("OMX.TI.Video.encoder", mComponentName)) { 647 if (portIndex == kPortIndexInput 648 && colorFormat == format.eColorFormat) { 649 // eCompressionFormat does not seem right. 650 found = true; 651 break; 652 } 653 if (portIndex == kPortIndexOutput 654 && compressionFormat == format.eCompressionFormat) { 655 // eColorFormat does not seem right. 656 found = true; 657 break; 658 } 659 } 660 661 if (format.eCompressionFormat == compressionFormat 662 && format.eColorFormat == colorFormat) { 663 found = true; 664 break; 665 } 666 667 ++index; 668 } 669 670 if (!found) { 671 return UNKNOWN_ERROR; 672 } 673 674 CODEC_LOGV("found a match."); 675 status_t err = mOMX->setParameter( 676 mNode, OMX_IndexParamVideoPortFormat, 677 &format, sizeof(format)); 678 679 return err; 680} 681 682static size_t getFrameSize( 683 OMX_COLOR_FORMATTYPE colorFormat, int32_t width, int32_t height) { 684 switch (colorFormat) { 685 case OMX_COLOR_FormatYCbYCr: 686 case OMX_COLOR_FormatCbYCrY: 687 return width * height * 2; 688 689 case OMX_COLOR_FormatYUV420Planar: 690 case OMX_COLOR_FormatYUV420SemiPlanar: 691 return (width * height * 3) / 2; 692 693 default: 694 CHECK(!"Should not be here. Unsupported color format."); 695 break; 696 } 697} 698 699void OMXCodec::setVideoInputFormat( 700 const char *mime, OMX_U32 width, OMX_U32 height) { 701 CODEC_LOGV("setVideoInputFormat width=%ld, height=%ld", width, height); 702 703 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; 704 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 705 compressionFormat = OMX_VIDEO_CodingAVC; 706 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 707 compressionFormat = OMX_VIDEO_CodingMPEG4; 708 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 709 compressionFormat = OMX_VIDEO_CodingH263; 710 } else { 711 LOGE("Not a supported video mime type: %s", mime); 712 CHECK(!"Should not be here. Not a supported video mime type."); 713 } 714 715 OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FormatYUV420SemiPlanar; 716 if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) { 717 colorFormat = OMX_COLOR_FormatYCbYCr; 718 } 719 720 721 722 status_t err; 723 OMX_PARAM_PORTDEFINITIONTYPE def; 724 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 725 726 //////////////////////// Input port ///////////////////////// 727 CHECK_EQ(setVideoPortFormatType( 728 kPortIndexInput, OMX_VIDEO_CodingUnused, 729 colorFormat), OK); 730 InitOMXParams(&def); 731 def.nPortIndex = kPortIndexInput; 732 733 err = mOMX->getParameter( 734 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 735 CHECK_EQ(err, OK); 736 737 def.nBufferSize = getFrameSize(colorFormat, width, height); 738 739 CHECK_EQ(def.eDomain, OMX_PortDomainVideo); 740 741 video_def->nFrameWidth = width; 742 video_def->nFrameHeight = height; 743 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 744 video_def->eColorFormat = colorFormat; 745 746 video_def->xFramerate = (24 << 16); // Q16 format 747 748 err = mOMX->setParameter( 749 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 750 CHECK_EQ(err, OK); 751 752 //////////////////////// Output port ///////////////////////// 753 CHECK_EQ(setVideoPortFormatType( 754 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused), 755 OK); 756 InitOMXParams(&def); 757 def.nPortIndex = kPortIndexOutput; 758 759 err = mOMX->getParameter( 760 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 761 762 CHECK_EQ(err, OK); 763 CHECK_EQ(def.eDomain, OMX_PortDomainVideo); 764 765 video_def->nFrameWidth = width; 766 video_def->nFrameHeight = height; 767 768 video_def->eCompressionFormat = compressionFormat; 769 video_def->eColorFormat = OMX_COLOR_FormatUnused; 770 771 err = mOMX->setParameter( 772 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 773 CHECK_EQ(err, OK); 774 775 /////////////////// Codec-specific //////////////////////// 776 switch (compressionFormat) { 777 case OMX_VIDEO_CodingMPEG4: 778 { 779 CHECK_EQ(setupMPEG4EncoderParameters(), OK); 780 break; 781 } 782 783 case OMX_VIDEO_CodingH263: 784 break; 785 786 case OMX_VIDEO_CodingAVC: 787 { 788 CHECK_EQ(setupAVCEncoderParameters(), OK); 789 break; 790 } 791 792 default: 793 CHECK(!"Support for this compressionFormat to be implemented."); 794 break; 795 } 796} 797 798status_t OMXCodec::setupMPEG4EncoderParameters() { 799 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 800 InitOMXParams(&mpeg4type); 801 mpeg4type.nPortIndex = kPortIndexOutput; 802 803 status_t err = mOMX->getParameter( 804 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 805 CHECK_EQ(err, OK); 806 807 mpeg4type.nSliceHeaderSpacing = 0; 808 mpeg4type.bSVH = OMX_FALSE; 809 mpeg4type.bGov = OMX_FALSE; 810 811 mpeg4type.nAllowedPictureTypes = 812 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 813 814 mpeg4type.nPFrames = 23; 815 mpeg4type.nBFrames = 0; 816 817 mpeg4type.nIDCVLCThreshold = 0; 818 mpeg4type.bACPred = OMX_TRUE; 819 mpeg4type.nMaxPacketSize = 256; 820 mpeg4type.nTimeIncRes = 1000; 821 mpeg4type.nHeaderExtension = 0; 822 mpeg4type.bReversibleVLC = OMX_FALSE; 823 824 mpeg4type.eProfile = OMX_VIDEO_MPEG4ProfileCore; 825 mpeg4type.eLevel = OMX_VIDEO_MPEG4Level2; 826 827 err = mOMX->setParameter( 828 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 829 CHECK_EQ(err, OK); 830 831 // ---------------- 832 833 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 834 InitOMXParams(&bitrateType); 835 bitrateType.nPortIndex = kPortIndexOutput; 836 837 err = mOMX->getParameter( 838 mNode, OMX_IndexParamVideoBitrate, 839 &bitrateType, sizeof(bitrateType)); 840 CHECK_EQ(err, OK); 841 842 bitrateType.eControlRate = OMX_Video_ControlRateVariable; 843 bitrateType.nTargetBitrate = 1000000; 844 845 err = mOMX->setParameter( 846 mNode, OMX_IndexParamVideoBitrate, 847 &bitrateType, sizeof(bitrateType)); 848 CHECK_EQ(err, OK); 849 850 // ---------------- 851 852 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 853 InitOMXParams(&errorCorrectionType); 854 errorCorrectionType.nPortIndex = kPortIndexOutput; 855 856 err = mOMX->getParameter( 857 mNode, OMX_IndexParamVideoErrorCorrection, 858 &errorCorrectionType, sizeof(errorCorrectionType)); 859 CHECK_EQ(err, OK); 860 861 errorCorrectionType.bEnableHEC = OMX_FALSE; 862 errorCorrectionType.bEnableResync = OMX_TRUE; 863 errorCorrectionType.nResynchMarkerSpacing = 256; 864 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 865 errorCorrectionType.bEnableRVLC = OMX_FALSE; 866 867 err = mOMX->setParameter( 868 mNode, OMX_IndexParamVideoErrorCorrection, 869 &errorCorrectionType, sizeof(errorCorrectionType)); 870 CHECK_EQ(err, OK); 871 872 return OK; 873} 874 875status_t OMXCodec::setupAVCEncoderParameters() { 876 OMX_VIDEO_PARAM_AVCTYPE h264type; 877 InitOMXParams(&h264type); 878 h264type.nPortIndex = kPortIndexOutput; 879 880 status_t err = mOMX->getParameter( 881 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 882 CHECK_EQ(err, OK); 883 884 h264type.nAllowedPictureTypes = 885 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 886 887 h264type.nSliceHeaderSpacing = 0; 888 h264type.nBFrames = 0; 889 h264type.bUseHadamard = OMX_TRUE; 890 h264type.nRefFrames = 1; 891 h264type.nRefIdx10ActiveMinus1 = 0; 892 h264type.nRefIdx11ActiveMinus1 = 0; 893 h264type.bEnableUEP = OMX_FALSE; 894 h264type.bEnableFMO = OMX_FALSE; 895 h264type.bEnableASO = OMX_FALSE; 896 h264type.bEnableRS = OMX_FALSE; 897 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 898 h264type.eLevel = OMX_VIDEO_AVCLevel1b; 899 h264type.bFrameMBsOnly = OMX_TRUE; 900 h264type.bMBAFF = OMX_FALSE; 901 h264type.bEntropyCodingCABAC = OMX_FALSE; 902 h264type.bWeightedPPrediction = OMX_FALSE; 903 h264type.bconstIpred = OMX_FALSE; 904 h264type.bDirect8x8Inference = OMX_FALSE; 905 h264type.bDirectSpatialTemporal = OMX_FALSE; 906 h264type.nCabacInitIdc = 0; 907 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 908 909 err = mOMX->setParameter( 910 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 911 CHECK_EQ(err, OK); 912 913 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 914 InitOMXParams(&bitrateType); 915 bitrateType.nPortIndex = kPortIndexOutput; 916 917 err = mOMX->getParameter( 918 mNode, OMX_IndexParamVideoBitrate, 919 &bitrateType, sizeof(bitrateType)); 920 CHECK_EQ(err, OK); 921 922 bitrateType.eControlRate = OMX_Video_ControlRateVariable; 923 bitrateType.nTargetBitrate = 3000000; 924 925 err = mOMX->setParameter( 926 mNode, OMX_IndexParamVideoBitrate, 927 &bitrateType, sizeof(bitrateType)); 928 CHECK_EQ(err, OK); 929 930 return OK; 931} 932 933status_t OMXCodec::setVideoOutputFormat( 934 const char *mime, OMX_U32 width, OMX_U32 height) { 935 CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height); 936 937 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; 938 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 939 compressionFormat = OMX_VIDEO_CodingAVC; 940 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 941 compressionFormat = OMX_VIDEO_CodingMPEG4; 942 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 943 compressionFormat = OMX_VIDEO_CodingH263; 944 } else { 945 LOGE("Not a supported video mime type: %s", mime); 946 CHECK(!"Should not be here. Not a supported video mime type."); 947 } 948 949 status_t err = setVideoPortFormatType( 950 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 951 952 if (err != OK) { 953 return err; 954 } 955 956#if 1 957 { 958 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 959 InitOMXParams(&format); 960 format.nPortIndex = kPortIndexOutput; 961 format.nIndex = 0; 962 963 status_t err = mOMX->getParameter( 964 mNode, OMX_IndexParamVideoPortFormat, 965 &format, sizeof(format)); 966 CHECK_EQ(err, OK); 967 CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused); 968 969 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; 970 971 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar 972 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 973 || format.eColorFormat == OMX_COLOR_FormatCbYCrY 974 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); 975 976 err = mOMX->setParameter( 977 mNode, OMX_IndexParamVideoPortFormat, 978 &format, sizeof(format)); 979 980 if (err != OK) { 981 return err; 982 } 983 } 984#endif 985 986 OMX_PARAM_PORTDEFINITIONTYPE def; 987 InitOMXParams(&def); 988 def.nPortIndex = kPortIndexInput; 989 990 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 991 992 err = mOMX->getParameter( 993 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 994 995 CHECK_EQ(err, OK); 996 997#if 1 998 // XXX Need a (much) better heuristic to compute input buffer sizes. 999 const size_t X = 64 * 1024; 1000 if (def.nBufferSize < X) { 1001 def.nBufferSize = X; 1002 } 1003#endif 1004 1005 CHECK_EQ(def.eDomain, OMX_PortDomainVideo); 1006 1007 video_def->nFrameWidth = width; 1008 video_def->nFrameHeight = height; 1009 1010 video_def->eCompressionFormat = compressionFormat; 1011 video_def->eColorFormat = OMX_COLOR_FormatUnused; 1012 1013 err = mOMX->setParameter( 1014 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1015 1016 if (err != OK) { 1017 return err; 1018 } 1019 1020 //////////////////////////////////////////////////////////////////////////// 1021 1022 InitOMXParams(&def); 1023 def.nPortIndex = kPortIndexOutput; 1024 1025 err = mOMX->getParameter( 1026 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1027 CHECK_EQ(err, OK); 1028 CHECK_EQ(def.eDomain, OMX_PortDomainVideo); 1029 1030#if 0 1031 def.nBufferSize = 1032 (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420 1033#endif 1034 1035 video_def->nFrameWidth = width; 1036 video_def->nFrameHeight = height; 1037 1038 err = mOMX->setParameter( 1039 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1040 1041 return err; 1042} 1043 1044OMXCodec::OMXCodec( 1045 const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks, 1046 bool isEncoder, 1047 const char *mime, 1048 const char *componentName, 1049 const sp<MediaSource> &source) 1050 : mOMX(omx), 1051 mOMXLivesLocally(omx->livesLocally(getpid())), 1052 mNode(node), 1053 mQuirks(quirks), 1054 mIsEncoder(isEncoder), 1055 mMIME(strdup(mime)), 1056 mComponentName(strdup(componentName)), 1057 mSource(source), 1058 mCodecSpecificDataIndex(0), 1059 mState(LOADED), 1060 mInitialBufferSubmit(true), 1061 mSignalledEOS(false), 1062 mNoMoreOutputData(false), 1063 mOutputPortSettingsHaveChanged(false), 1064 mSeekTimeUs(-1), 1065 mLeftOverBuffer(NULL) { 1066 mPortStatus[kPortIndexInput] = ENABLED; 1067 mPortStatus[kPortIndexOutput] = ENABLED; 1068 1069 setComponentRole(); 1070} 1071 1072// static 1073void OMXCodec::setComponentRole( 1074 const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder, 1075 const char *mime) { 1076 struct MimeToRole { 1077 const char *mime; 1078 const char *decoderRole; 1079 const char *encoderRole; 1080 }; 1081 1082 static const MimeToRole kMimeToRole[] = { 1083 { MEDIA_MIMETYPE_AUDIO_MPEG, 1084 "audio_decoder.mp3", "audio_encoder.mp3" }, 1085 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 1086 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 1087 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 1088 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 1089 { MEDIA_MIMETYPE_AUDIO_AAC, 1090 "audio_decoder.aac", "audio_encoder.aac" }, 1091 { MEDIA_MIMETYPE_VIDEO_AVC, 1092 "video_decoder.avc", "video_encoder.avc" }, 1093 { MEDIA_MIMETYPE_VIDEO_MPEG4, 1094 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 1095 { MEDIA_MIMETYPE_VIDEO_H263, 1096 "video_decoder.h263", "video_encoder.h263" }, 1097 }; 1098 1099 static const size_t kNumMimeToRole = 1100 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 1101 1102 size_t i; 1103 for (i = 0; i < kNumMimeToRole; ++i) { 1104 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 1105 break; 1106 } 1107 } 1108 1109 if (i == kNumMimeToRole) { 1110 return; 1111 } 1112 1113 const char *role = 1114 isEncoder ? kMimeToRole[i].encoderRole 1115 : kMimeToRole[i].decoderRole; 1116 1117 if (role != NULL) { 1118 OMX_PARAM_COMPONENTROLETYPE roleParams; 1119 InitOMXParams(&roleParams); 1120 1121 strncpy((char *)roleParams.cRole, 1122 role, OMX_MAX_STRINGNAME_SIZE - 1); 1123 1124 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 1125 1126 status_t err = omx->setParameter( 1127 node, OMX_IndexParamStandardComponentRole, 1128 &roleParams, sizeof(roleParams)); 1129 1130 if (err != OK) { 1131 LOGW("Failed to set standard component role '%s'.", role); 1132 } 1133 } 1134} 1135 1136void OMXCodec::setComponentRole() { 1137 setComponentRole(mOMX, mNode, mIsEncoder, mMIME); 1138} 1139 1140OMXCodec::~OMXCodec() { 1141 CHECK(mState == LOADED || mState == ERROR); 1142 1143 status_t err = mOMX->freeNode(mNode); 1144 CHECK_EQ(err, OK); 1145 1146 mNode = NULL; 1147 setState(DEAD); 1148 1149 clearCodecSpecificData(); 1150 1151 free(mComponentName); 1152 mComponentName = NULL; 1153 1154 free(mMIME); 1155 mMIME = NULL; 1156} 1157 1158status_t OMXCodec::init() { 1159 // mLock is held. 1160 1161 CHECK_EQ(mState, LOADED); 1162 1163 status_t err; 1164 if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) { 1165 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); 1166 CHECK_EQ(err, OK); 1167 setState(LOADED_TO_IDLE); 1168 } 1169 1170 err = allocateBuffers(); 1171 CHECK_EQ(err, OK); 1172 1173 if (mQuirks & kRequiresLoadedToIdleAfterAllocation) { 1174 err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); 1175 CHECK_EQ(err, OK); 1176 1177 setState(LOADED_TO_IDLE); 1178 } 1179 1180 while (mState != EXECUTING && mState != ERROR) { 1181 mAsyncCompletion.wait(mLock); 1182 } 1183 1184 return mState == ERROR ? UNKNOWN_ERROR : OK; 1185} 1186 1187// static 1188bool OMXCodec::isIntermediateState(State state) { 1189 return state == LOADED_TO_IDLE 1190 || state == IDLE_TO_EXECUTING 1191 || state == EXECUTING_TO_IDLE 1192 || state == IDLE_TO_LOADED 1193 || state == RECONFIGURING; 1194} 1195 1196status_t OMXCodec::allocateBuffers() { 1197 status_t err = allocateBuffersOnPort(kPortIndexInput); 1198 1199 if (err != OK) { 1200 return err; 1201 } 1202 1203 return allocateBuffersOnPort(kPortIndexOutput); 1204} 1205 1206status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) { 1207 OMX_PARAM_PORTDEFINITIONTYPE def; 1208 InitOMXParams(&def); 1209 def.nPortIndex = portIndex; 1210 1211 status_t err = mOMX->getParameter( 1212 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1213 1214 if (err != OK) { 1215 return err; 1216 } 1217 1218 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 1219 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec"); 1220 1221 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 1222 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 1223 CHECK(mem.get() != NULL); 1224 1225 BufferInfo info; 1226 info.mData = NULL; 1227 info.mSize = def.nBufferSize; 1228 1229 IOMX::buffer_id buffer; 1230 if (portIndex == kPortIndexInput 1231 && (mQuirks & kRequiresAllocateBufferOnInputPorts)) { 1232 if (mOMXLivesLocally) { 1233 mem.clear(); 1234 1235 err = mOMX->allocateBuffer( 1236 mNode, portIndex, def.nBufferSize, &buffer, 1237 &info.mData); 1238 } else { 1239 err = mOMX->allocateBufferWithBackup( 1240 mNode, portIndex, mem, &buffer); 1241 } 1242 } else if (portIndex == kPortIndexOutput 1243 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) { 1244 if (mOMXLivesLocally) { 1245 mem.clear(); 1246 1247 err = mOMX->allocateBuffer( 1248 mNode, portIndex, def.nBufferSize, &buffer, 1249 &info.mData); 1250 } else { 1251 err = mOMX->allocateBufferWithBackup( 1252 mNode, portIndex, mem, &buffer); 1253 } 1254 } else { 1255 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); 1256 } 1257 1258 if (err != OK) { 1259 LOGE("allocate_buffer_with_backup failed"); 1260 return err; 1261 } 1262 1263 if (mem != NULL) { 1264 info.mData = mem->pointer(); 1265 } 1266 1267 info.mBuffer = buffer; 1268 info.mOwnedByComponent = false; 1269 info.mMem = mem; 1270 info.mMediaBuffer = NULL; 1271 1272 if (portIndex == kPortIndexOutput) { 1273 if (!(mOMXLivesLocally 1274 && (mQuirks & kRequiresAllocateBufferOnOutputPorts) 1275 && (mQuirks & kDefersOutputBufferAllocation))) { 1276 // If the node does not fill in the buffer ptr at this time, 1277 // we will defer creating the MediaBuffer until receiving 1278 // the first FILL_BUFFER_DONE notification instead. 1279 info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize); 1280 info.mMediaBuffer->setObserver(this); 1281 } 1282 } 1283 1284 mPortBuffers[portIndex].push(info); 1285 1286 CODEC_LOGV("allocated buffer %p on %s port", buffer, 1287 portIndex == kPortIndexInput ? "input" : "output"); 1288 } 1289 1290 // dumpPortStatus(portIndex); 1291 1292 return OK; 1293} 1294 1295void OMXCodec::on_message(const omx_message &msg) { 1296 Mutex::Autolock autoLock(mLock); 1297 1298 switch (msg.type) { 1299 case omx_message::EVENT: 1300 { 1301 onEvent( 1302 msg.u.event_data.event, msg.u.event_data.data1, 1303 msg.u.event_data.data2); 1304 1305 break; 1306 } 1307 1308 case omx_message::EMPTY_BUFFER_DONE: 1309 { 1310 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer; 1311 1312 CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer); 1313 1314 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput]; 1315 size_t i = 0; 1316 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) { 1317 ++i; 1318 } 1319 1320 CHECK(i < buffers->size()); 1321 if (!(*buffers)[i].mOwnedByComponent) { 1322 LOGW("We already own input buffer %p, yet received " 1323 "an EMPTY_BUFFER_DONE.", buffer); 1324 } 1325 1326 buffers->editItemAt(i).mOwnedByComponent = false; 1327 1328 if (mPortStatus[kPortIndexInput] == DISABLING) { 1329 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer); 1330 1331 status_t err = 1332 mOMX->freeBuffer(mNode, kPortIndexInput, buffer); 1333 CHECK_EQ(err, OK); 1334 1335 buffers->removeAt(i); 1336 } else if (mState != ERROR 1337 && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) { 1338 CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED); 1339 drainInputBuffer(&buffers->editItemAt(i)); 1340 } 1341 break; 1342 } 1343 1344 case omx_message::FILL_BUFFER_DONE: 1345 { 1346 IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer; 1347 OMX_U32 flags = msg.u.extended_buffer_data.flags; 1348 1349 CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx, timestamp: %lld us (%.2f secs))", 1350 buffer, 1351 msg.u.extended_buffer_data.range_length, 1352 flags, 1353 msg.u.extended_buffer_data.timestamp, 1354 msg.u.extended_buffer_data.timestamp / 1E6); 1355 1356 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput]; 1357 size_t i = 0; 1358 while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) { 1359 ++i; 1360 } 1361 1362 CHECK(i < buffers->size()); 1363 BufferInfo *info = &buffers->editItemAt(i); 1364 1365 if (!info->mOwnedByComponent) { 1366 LOGW("We already own output buffer %p, yet received " 1367 "a FILL_BUFFER_DONE.", buffer); 1368 } 1369 1370 info->mOwnedByComponent = false; 1371 1372 if (mPortStatus[kPortIndexOutput] == DISABLING) { 1373 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer); 1374 1375 status_t err = 1376 mOMX->freeBuffer(mNode, kPortIndexOutput, buffer); 1377 CHECK_EQ(err, OK); 1378 1379 buffers->removeAt(i); 1380#if 0 1381 } else if (mPortStatus[kPortIndexOutput] == ENABLED 1382 && (flags & OMX_BUFFERFLAG_EOS)) { 1383 CODEC_LOGV("No more output data."); 1384 mNoMoreOutputData = true; 1385 mBufferFilled.signal(); 1386#endif 1387 } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) { 1388 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED); 1389 1390 if (info->mMediaBuffer == NULL) { 1391 CHECK(mOMXLivesLocally); 1392 CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts); 1393 CHECK(mQuirks & kDefersOutputBufferAllocation); 1394 1395 // The qcom video decoders on Nexus don't actually allocate 1396 // output buffer memory on a call to OMX_AllocateBuffer 1397 // the "pBuffer" member of the OMX_BUFFERHEADERTYPE 1398 // structure is only filled in later. 1399 1400 info->mMediaBuffer = new MediaBuffer( 1401 msg.u.extended_buffer_data.data_ptr, 1402 info->mSize); 1403 info->mMediaBuffer->setObserver(this); 1404 } 1405 1406 MediaBuffer *buffer = info->mMediaBuffer; 1407 1408 buffer->set_range( 1409 msg.u.extended_buffer_data.range_offset, 1410 msg.u.extended_buffer_data.range_length); 1411 1412 buffer->meta_data()->clear(); 1413 1414 buffer->meta_data()->setInt64( 1415 kKeyTime, msg.u.extended_buffer_data.timestamp); 1416 1417 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) { 1418 buffer->meta_data()->setInt32(kKeyIsSyncFrame, true); 1419 } 1420 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) { 1421 buffer->meta_data()->setInt32(kKeyIsCodecConfig, true); 1422 } 1423 1424 buffer->meta_data()->setPointer( 1425 kKeyPlatformPrivate, 1426 msg.u.extended_buffer_data.platform_private); 1427 1428 buffer->meta_data()->setPointer( 1429 kKeyBufferID, 1430 msg.u.extended_buffer_data.buffer); 1431 1432 mFilledBuffers.push_back(i); 1433 mBufferFilled.signal(); 1434 1435 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) { 1436 CODEC_LOGV("No more output data."); 1437 mNoMoreOutputData = true; 1438 } 1439 } 1440 1441 break; 1442 } 1443 1444 default: 1445 { 1446 CHECK(!"should not be here."); 1447 break; 1448 } 1449 } 1450} 1451 1452void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1453 switch (event) { 1454 case OMX_EventCmdComplete: 1455 { 1456 onCmdComplete((OMX_COMMANDTYPE)data1, data2); 1457 break; 1458 } 1459 1460 case OMX_EventError: 1461 { 1462 LOGE("ERROR(0x%08lx, %ld)", data1, data2); 1463 1464 setState(ERROR); 1465 break; 1466 } 1467 1468 case OMX_EventPortSettingsChanged: 1469 { 1470 onPortSettingsChanged(data1); 1471 break; 1472 } 1473 1474#if 0 1475 case OMX_EventBufferFlag: 1476 { 1477 CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1); 1478 1479 if (data1 == kPortIndexOutput) { 1480 mNoMoreOutputData = true; 1481 } 1482 break; 1483 } 1484#endif 1485 1486 default: 1487 { 1488 CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2); 1489 break; 1490 } 1491 } 1492} 1493 1494// Has the format changed in any way that the client would have to be aware of? 1495static bool formatHasNotablyChanged( 1496 const sp<MetaData> &from, const sp<MetaData> &to) { 1497 if (from.get() == NULL && to.get() == NULL) { 1498 return false; 1499 } 1500 1501 if ((from.get() == NULL && to.get() != NULL) 1502 || (from.get() != NULL && to.get() == NULL)) { 1503 return true; 1504 } 1505 1506 const char *mime_from, *mime_to; 1507 CHECK(from->findCString(kKeyMIMEType, &mime_from)); 1508 CHECK(to->findCString(kKeyMIMEType, &mime_to)); 1509 1510 if (strcasecmp(mime_from, mime_to)) { 1511 return true; 1512 } 1513 1514 if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) { 1515 int32_t colorFormat_from, colorFormat_to; 1516 CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from)); 1517 CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to)); 1518 1519 if (colorFormat_from != colorFormat_to) { 1520 return true; 1521 } 1522 1523 int32_t width_from, width_to; 1524 CHECK(from->findInt32(kKeyWidth, &width_from)); 1525 CHECK(to->findInt32(kKeyWidth, &width_to)); 1526 1527 if (width_from != width_to) { 1528 return true; 1529 } 1530 1531 int32_t height_from, height_to; 1532 CHECK(from->findInt32(kKeyHeight, &height_from)); 1533 CHECK(to->findInt32(kKeyHeight, &height_to)); 1534 1535 if (height_from != height_to) { 1536 return true; 1537 } 1538 } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) { 1539 int32_t numChannels_from, numChannels_to; 1540 CHECK(from->findInt32(kKeyChannelCount, &numChannels_from)); 1541 CHECK(to->findInt32(kKeyChannelCount, &numChannels_to)); 1542 1543 if (numChannels_from != numChannels_to) { 1544 return true; 1545 } 1546 1547 int32_t sampleRate_from, sampleRate_to; 1548 CHECK(from->findInt32(kKeySampleRate, &sampleRate_from)); 1549 CHECK(to->findInt32(kKeySampleRate, &sampleRate_to)); 1550 1551 if (sampleRate_from != sampleRate_to) { 1552 return true; 1553 } 1554 } 1555 1556 return false; 1557} 1558 1559void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { 1560 switch (cmd) { 1561 case OMX_CommandStateSet: 1562 { 1563 onStateChange((OMX_STATETYPE)data); 1564 break; 1565 } 1566 1567 case OMX_CommandPortDisable: 1568 { 1569 OMX_U32 portIndex = data; 1570 CODEC_LOGV("PORT_DISABLED(%ld)", portIndex); 1571 1572 CHECK(mState == EXECUTING || mState == RECONFIGURING); 1573 CHECK_EQ(mPortStatus[portIndex], DISABLING); 1574 CHECK_EQ(mPortBuffers[portIndex].size(), 0); 1575 1576 mPortStatus[portIndex] = DISABLED; 1577 1578 if (mState == RECONFIGURING) { 1579 CHECK_EQ(portIndex, kPortIndexOutput); 1580 1581 sp<MetaData> oldOutputFormat = mOutputFormat; 1582 initOutputFormat(mSource->getFormat()); 1583 1584 // Don't notify clients if the output port settings change 1585 // wasn't of importance to them, i.e. it may be that just the 1586 // number of buffers has changed and nothing else. 1587 mOutputPortSettingsHaveChanged = 1588 formatHasNotablyChanged(oldOutputFormat, mOutputFormat); 1589 1590 enablePortAsync(portIndex); 1591 1592 status_t err = allocateBuffersOnPort(portIndex); 1593 CHECK_EQ(err, OK); 1594 } 1595 break; 1596 } 1597 1598 case OMX_CommandPortEnable: 1599 { 1600 OMX_U32 portIndex = data; 1601 CODEC_LOGV("PORT_ENABLED(%ld)", portIndex); 1602 1603 CHECK(mState == EXECUTING || mState == RECONFIGURING); 1604 CHECK_EQ(mPortStatus[portIndex], ENABLING); 1605 1606 mPortStatus[portIndex] = ENABLED; 1607 1608 if (mState == RECONFIGURING) { 1609 CHECK_EQ(portIndex, kPortIndexOutput); 1610 1611 setState(EXECUTING); 1612 1613 fillOutputBuffers(); 1614 } 1615 break; 1616 } 1617 1618 case OMX_CommandFlush: 1619 { 1620 OMX_U32 portIndex = data; 1621 1622 CODEC_LOGV("FLUSH_DONE(%ld)", portIndex); 1623 1624 CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN); 1625 mPortStatus[portIndex] = ENABLED; 1626 1627 CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]), 1628 mPortBuffers[portIndex].size()); 1629 1630 if (mState == RECONFIGURING) { 1631 CHECK_EQ(portIndex, kPortIndexOutput); 1632 1633 disablePortAsync(portIndex); 1634 } else if (mState == EXECUTING_TO_IDLE) { 1635 if (mPortStatus[kPortIndexInput] == ENABLED 1636 && mPortStatus[kPortIndexOutput] == ENABLED) { 1637 CODEC_LOGV("Finished flushing both ports, now completing " 1638 "transition from EXECUTING to IDLE."); 1639 1640 mPortStatus[kPortIndexInput] = SHUTTING_DOWN; 1641 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN; 1642 1643 status_t err = 1644 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); 1645 CHECK_EQ(err, OK); 1646 } 1647 } else { 1648 // We're flushing both ports in preparation for seeking. 1649 1650 if (mPortStatus[kPortIndexInput] == ENABLED 1651 && mPortStatus[kPortIndexOutput] == ENABLED) { 1652 CODEC_LOGV("Finished flushing both ports, now continuing from" 1653 " seek-time."); 1654 1655 drainInputBuffers(); 1656 fillOutputBuffers(); 1657 } 1658 } 1659 1660 break; 1661 } 1662 1663 default: 1664 { 1665 CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data); 1666 break; 1667 } 1668 } 1669} 1670 1671void OMXCodec::onStateChange(OMX_STATETYPE newState) { 1672 CODEC_LOGV("onStateChange %d", newState); 1673 1674 switch (newState) { 1675 case OMX_StateIdle: 1676 { 1677 CODEC_LOGV("Now Idle."); 1678 if (mState == LOADED_TO_IDLE) { 1679 status_t err = mOMX->sendCommand( 1680 mNode, OMX_CommandStateSet, OMX_StateExecuting); 1681 1682 CHECK_EQ(err, OK); 1683 1684 setState(IDLE_TO_EXECUTING); 1685 } else { 1686 CHECK_EQ(mState, EXECUTING_TO_IDLE); 1687 1688 CHECK_EQ( 1689 countBuffersWeOwn(mPortBuffers[kPortIndexInput]), 1690 mPortBuffers[kPortIndexInput].size()); 1691 1692 CHECK_EQ( 1693 countBuffersWeOwn(mPortBuffers[kPortIndexOutput]), 1694 mPortBuffers[kPortIndexOutput].size()); 1695 1696 status_t err = mOMX->sendCommand( 1697 mNode, OMX_CommandStateSet, OMX_StateLoaded); 1698 1699 CHECK_EQ(err, OK); 1700 1701 err = freeBuffersOnPort(kPortIndexInput); 1702 CHECK_EQ(err, OK); 1703 1704 err = freeBuffersOnPort(kPortIndexOutput); 1705 CHECK_EQ(err, OK); 1706 1707 mPortStatus[kPortIndexInput] = ENABLED; 1708 mPortStatus[kPortIndexOutput] = ENABLED; 1709 1710 setState(IDLE_TO_LOADED); 1711 } 1712 break; 1713 } 1714 1715 case OMX_StateExecuting: 1716 { 1717 CHECK_EQ(mState, IDLE_TO_EXECUTING); 1718 1719 CODEC_LOGV("Now Executing."); 1720 1721 setState(EXECUTING); 1722 1723 // Buffers will be submitted to the component in the first 1724 // call to OMXCodec::read as mInitialBufferSubmit is true at 1725 // this point. This ensures that this on_message call returns, 1726 // releases the lock and ::init can notice the state change and 1727 // itself return. 1728 break; 1729 } 1730 1731 case OMX_StateLoaded: 1732 { 1733 CHECK_EQ(mState, IDLE_TO_LOADED); 1734 1735 CODEC_LOGV("Now Loaded."); 1736 1737 setState(LOADED); 1738 break; 1739 } 1740 1741 case OMX_StateInvalid: 1742 { 1743 setState(ERROR); 1744 break; 1745 } 1746 1747 default: 1748 { 1749 CHECK(!"should not be here."); 1750 break; 1751 } 1752 } 1753} 1754 1755// static 1756size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) { 1757 size_t n = 0; 1758 for (size_t i = 0; i < buffers.size(); ++i) { 1759 if (!buffers[i].mOwnedByComponent) { 1760 ++n; 1761 } 1762 } 1763 1764 return n; 1765} 1766 1767status_t OMXCodec::freeBuffersOnPort( 1768 OMX_U32 portIndex, bool onlyThoseWeOwn) { 1769 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1770 1771 status_t stickyErr = OK; 1772 1773 for (size_t i = buffers->size(); i-- > 0;) { 1774 BufferInfo *info = &buffers->editItemAt(i); 1775 1776 if (onlyThoseWeOwn && info->mOwnedByComponent) { 1777 continue; 1778 } 1779 1780 CHECK_EQ(info->mOwnedByComponent, false); 1781 1782 CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex); 1783 1784 status_t err = 1785 mOMX->freeBuffer(mNode, portIndex, info->mBuffer); 1786 1787 if (err != OK) { 1788 stickyErr = err; 1789 } 1790 1791 if (info->mMediaBuffer != NULL) { 1792 info->mMediaBuffer->setObserver(NULL); 1793 1794 // Make sure nobody but us owns this buffer at this point. 1795 CHECK_EQ(info->mMediaBuffer->refcount(), 0); 1796 1797 info->mMediaBuffer->release(); 1798 } 1799 1800 buffers->removeAt(i); 1801 } 1802 1803 CHECK(onlyThoseWeOwn || buffers->isEmpty()); 1804 1805 return stickyErr; 1806} 1807 1808void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) { 1809 CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex); 1810 1811 CHECK_EQ(mState, EXECUTING); 1812 CHECK_EQ(portIndex, kPortIndexOutput); 1813 setState(RECONFIGURING); 1814 1815 if (mQuirks & kNeedsFlushBeforeDisable) { 1816 if (!flushPortAsync(portIndex)) { 1817 onCmdComplete(OMX_CommandFlush, portIndex); 1818 } 1819 } else { 1820 disablePortAsync(portIndex); 1821 } 1822} 1823 1824bool OMXCodec::flushPortAsync(OMX_U32 portIndex) { 1825 CHECK(mState == EXECUTING || mState == RECONFIGURING 1826 || mState == EXECUTING_TO_IDLE); 1827 1828 CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.", 1829 portIndex, countBuffersWeOwn(mPortBuffers[portIndex]), 1830 mPortBuffers[portIndex].size()); 1831 1832 CHECK_EQ(mPortStatus[portIndex], ENABLED); 1833 mPortStatus[portIndex] = SHUTTING_DOWN; 1834 1835 if ((mQuirks & kRequiresFlushCompleteEmulation) 1836 && countBuffersWeOwn(mPortBuffers[portIndex]) 1837 == mPortBuffers[portIndex].size()) { 1838 // No flush is necessary and this component fails to send a 1839 // flush-complete event in this case. 1840 1841 return false; 1842 } 1843 1844 status_t err = 1845 mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex); 1846 CHECK_EQ(err, OK); 1847 1848 return true; 1849} 1850 1851void OMXCodec::disablePortAsync(OMX_U32 portIndex) { 1852 CHECK(mState == EXECUTING || mState == RECONFIGURING); 1853 1854 CHECK_EQ(mPortStatus[portIndex], ENABLED); 1855 mPortStatus[portIndex] = DISABLING; 1856 1857 status_t err = 1858 mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex); 1859 CHECK_EQ(err, OK); 1860 1861 freeBuffersOnPort(portIndex, true); 1862} 1863 1864void OMXCodec::enablePortAsync(OMX_U32 portIndex) { 1865 CHECK(mState == EXECUTING || mState == RECONFIGURING); 1866 1867 CHECK_EQ(mPortStatus[portIndex], DISABLED); 1868 mPortStatus[portIndex] = ENABLING; 1869 1870 status_t err = 1871 mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex); 1872 CHECK_EQ(err, OK); 1873} 1874 1875void OMXCodec::fillOutputBuffers() { 1876 CHECK_EQ(mState, EXECUTING); 1877 1878 // This is a workaround for some decoders not properly reporting 1879 // end-of-output-stream. If we own all input buffers and also own 1880 // all output buffers and we already signalled end-of-input-stream, 1881 // the end-of-output-stream is implied. 1882 if (mSignalledEOS 1883 && countBuffersWeOwn(mPortBuffers[kPortIndexInput]) 1884 == mPortBuffers[kPortIndexInput].size() 1885 && countBuffersWeOwn(mPortBuffers[kPortIndexOutput]) 1886 == mPortBuffers[kPortIndexOutput].size()) { 1887 mNoMoreOutputData = true; 1888 mBufferFilled.signal(); 1889 1890 return; 1891 } 1892 1893 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput]; 1894 for (size_t i = 0; i < buffers->size(); ++i) { 1895 fillOutputBuffer(&buffers->editItemAt(i)); 1896 } 1897} 1898 1899void OMXCodec::drainInputBuffers() { 1900 CHECK(mState == EXECUTING || mState == RECONFIGURING); 1901 1902 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput]; 1903 for (size_t i = 0; i < buffers->size(); ++i) { 1904 drainInputBuffer(&buffers->editItemAt(i)); 1905 } 1906} 1907 1908void OMXCodec::drainInputBuffer(BufferInfo *info) { 1909 CHECK_EQ(info->mOwnedByComponent, false); 1910 1911 if (mSignalledEOS) { 1912 return; 1913 } 1914 1915 if (mCodecSpecificDataIndex < mCodecSpecificData.size()) { 1916 const CodecSpecificData *specific = 1917 mCodecSpecificData[mCodecSpecificDataIndex]; 1918 1919 size_t size = specific->mSize; 1920 1921 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME) 1922 && !(mQuirks & kWantsNALFragments)) { 1923 static const uint8_t kNALStartCode[4] = 1924 { 0x00, 0x00, 0x00, 0x01 }; 1925 1926 CHECK(info->mSize >= specific->mSize + 4); 1927 1928 size += 4; 1929 1930 memcpy(info->mData, kNALStartCode, 4); 1931 memcpy((uint8_t *)info->mData + 4, 1932 specific->mData, specific->mSize); 1933 } else { 1934 CHECK(info->mSize >= specific->mSize); 1935 memcpy(info->mData, specific->mData, specific->mSize); 1936 } 1937 1938 mNoMoreOutputData = false; 1939 1940 CODEC_LOGV("calling emptyBuffer with codec specific data"); 1941 1942 status_t err = mOMX->emptyBuffer( 1943 mNode, info->mBuffer, 0, size, 1944 OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG, 1945 0); 1946 CHECK_EQ(err, OK); 1947 1948 info->mOwnedByComponent = true; 1949 1950 ++mCodecSpecificDataIndex; 1951 return; 1952 } 1953 1954 status_t err; 1955 1956 bool signalEOS = false; 1957 int64_t timestampUs = 0; 1958 1959 size_t offset = 0; 1960 int32_t n = 0; 1961 for (;;) { 1962 MediaBuffer *srcBuffer; 1963 if (mSeekTimeUs >= 0) { 1964 if (mLeftOverBuffer) { 1965 mLeftOverBuffer->release(); 1966 mLeftOverBuffer = NULL; 1967 } 1968 1969 MediaSource::ReadOptions options; 1970 options.setSeekTo(mSeekTimeUs); 1971 1972 mSeekTimeUs = -1; 1973 mBufferFilled.signal(); 1974 1975 err = mSource->read(&srcBuffer, &options); 1976 } else if (mLeftOverBuffer) { 1977 srcBuffer = mLeftOverBuffer; 1978 mLeftOverBuffer = NULL; 1979 1980 err = OK; 1981 } else { 1982 err = mSource->read(&srcBuffer); 1983 } 1984 1985 if (err != OK) { 1986 signalEOS = true; 1987 mFinalStatus = err; 1988 mSignalledEOS = true; 1989 break; 1990 } 1991 1992 size_t remainingBytes = info->mSize - offset; 1993 1994 if (srcBuffer->range_length() > remainingBytes) { 1995 if (offset == 0) { 1996 CODEC_LOGE( 1997 "Codec's input buffers are too small to accomodate " 1998 "buffer read from source (info->mSize = %d, srcLength = %d)", 1999 info->mSize, srcBuffer->range_length()); 2000 2001 srcBuffer->release(); 2002 srcBuffer = NULL; 2003 2004 setState(ERROR); 2005 return; 2006 } 2007 2008 mLeftOverBuffer = srcBuffer; 2009 break; 2010 } 2011 2012 memcpy((uint8_t *)info->mData + offset, 2013 (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(), 2014 srcBuffer->range_length()); 2015 2016 int64_t lastBufferTimeUs; 2017 CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs)); 2018 CHECK(timestampUs >= 0); 2019 2020 if (offset == 0) { 2021 timestampUs = lastBufferTimeUs; 2022 } 2023 2024 offset += srcBuffer->range_length(); 2025 2026 srcBuffer->release(); 2027 srcBuffer = NULL; 2028 2029 ++n; 2030 2031 if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) { 2032 break; 2033 } 2034 2035 int64_t coalescedDurationUs = lastBufferTimeUs - timestampUs; 2036 2037 if (coalescedDurationUs > 250000ll) { 2038 // Don't coalesce more than 250ms worth of encoded data at once. 2039 break; 2040 } 2041 } 2042 2043 if (n > 1) { 2044 LOGV("coalesced %d frames into one input buffer", n); 2045 } 2046 2047 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 2048 2049 if (signalEOS) { 2050 flags |= OMX_BUFFERFLAG_EOS; 2051 } else { 2052 mNoMoreOutputData = false; 2053 } 2054 2055 CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), " 2056 "timestamp %lld us (%.2f secs)", 2057 info->mBuffer, offset, 2058 timestampUs, timestampUs / 1E6); 2059 2060 err = mOMX->emptyBuffer( 2061 mNode, info->mBuffer, 0, offset, 2062 flags, timestampUs); 2063 2064 if (err != OK) { 2065 setState(ERROR); 2066 return; 2067 } 2068 2069 info->mOwnedByComponent = true; 2070 2071 // This component does not ever signal the EOS flag on output buffers, 2072 // Thanks for nothing. 2073 if (mSignalledEOS && !strcmp(mComponentName, "OMX.TI.Video.encoder")) { 2074 mNoMoreOutputData = true; 2075 mBufferFilled.signal(); 2076 } 2077} 2078 2079void OMXCodec::fillOutputBuffer(BufferInfo *info) { 2080 CHECK_EQ(info->mOwnedByComponent, false); 2081 2082 if (mNoMoreOutputData) { 2083 CODEC_LOGV("There is no more output data available, not " 2084 "calling fillOutputBuffer"); 2085 return; 2086 } 2087 2088 CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer); 2089 status_t err = mOMX->fillBuffer(mNode, info->mBuffer); 2090 2091 if (err != OK) { 2092 CODEC_LOGE("fillBuffer failed w/ error 0x%08x", err); 2093 2094 setState(ERROR); 2095 return; 2096 } 2097 2098 info->mOwnedByComponent = true; 2099} 2100 2101void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) { 2102 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput]; 2103 for (size_t i = 0; i < buffers->size(); ++i) { 2104 if ((*buffers)[i].mBuffer == buffer) { 2105 drainInputBuffer(&buffers->editItemAt(i)); 2106 return; 2107 } 2108 } 2109 2110 CHECK(!"should not be here."); 2111} 2112 2113void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) { 2114 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput]; 2115 for (size_t i = 0; i < buffers->size(); ++i) { 2116 if ((*buffers)[i].mBuffer == buffer) { 2117 fillOutputBuffer(&buffers->editItemAt(i)); 2118 return; 2119 } 2120 } 2121 2122 CHECK(!"should not be here."); 2123} 2124 2125void OMXCodec::setState(State newState) { 2126 mState = newState; 2127 mAsyncCompletion.signal(); 2128 2129 // This may cause some spurious wakeups but is necessary to 2130 // unblock the reader if we enter ERROR state. 2131 mBufferFilled.signal(); 2132} 2133 2134void OMXCodec::setRawAudioFormat( 2135 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 2136 2137 // port definition 2138 OMX_PARAM_PORTDEFINITIONTYPE def; 2139 InitOMXParams(&def); 2140 def.nPortIndex = portIndex; 2141 status_t err = mOMX->getParameter( 2142 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2143 CHECK_EQ(err, OK); 2144 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 2145 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, 2146 &def, sizeof(def)), OK); 2147 2148 // pcm param 2149 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 2150 InitOMXParams(&pcmParams); 2151 pcmParams.nPortIndex = portIndex; 2152 2153 err = mOMX->getParameter( 2154 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2155 2156 CHECK_EQ(err, OK); 2157 2158 pcmParams.nChannels = numChannels; 2159 pcmParams.eNumData = OMX_NumericalDataSigned; 2160 pcmParams.bInterleaved = OMX_TRUE; 2161 pcmParams.nBitPerSample = 16; 2162 pcmParams.nSamplingRate = sampleRate; 2163 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 2164 2165 if (numChannels == 1) { 2166 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF; 2167 } else { 2168 CHECK_EQ(numChannels, 2); 2169 2170 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF; 2171 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF; 2172 } 2173 2174 err = mOMX->setParameter( 2175 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2176 2177 CHECK_EQ(err, OK); 2178} 2179 2180void OMXCodec::setAMRFormat(bool isWAMR) { 2181 OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput; 2182 2183 OMX_AUDIO_PARAM_AMRTYPE def; 2184 InitOMXParams(&def); 2185 def.nPortIndex = portIndex; 2186 2187 status_t err = 2188 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2189 2190 CHECK_EQ(err, OK); 2191 2192 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 2193 2194 // XXX: Select bandmode based on bit rate 2195 def.eAMRBandMode = 2196 isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0; 2197 2198 err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2199 CHECK_EQ(err, OK); 2200 2201 //////////////////////// 2202 2203 if (mIsEncoder) { 2204 sp<MetaData> format = mSource->getFormat(); 2205 int32_t sampleRate; 2206 int32_t numChannels; 2207 CHECK(format->findInt32(kKeySampleRate, &sampleRate)); 2208 CHECK(format->findInt32(kKeyChannelCount, &numChannels)); 2209 2210 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 2211 } 2212} 2213 2214void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) { 2215 CHECK(numChannels == 1 || numChannels == 2); 2216 if (mIsEncoder) { 2217 //////////////// input port //////////////////// 2218 setRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 2219 2220 //////////////// output port //////////////////// 2221 // format 2222 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 2223 format.nPortIndex = kPortIndexOutput; 2224 format.nIndex = 0; 2225 status_t err = OMX_ErrorNone; 2226 while (OMX_ErrorNone == err) { 2227 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat, 2228 &format, sizeof(format)), OK); 2229 if (format.eEncoding == OMX_AUDIO_CodingAAC) { 2230 break; 2231 } 2232 format.nIndex++; 2233 } 2234 CHECK_EQ(OK, err); 2235 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat, 2236 &format, sizeof(format)), OK); 2237 2238 // port definition 2239 OMX_PARAM_PORTDEFINITIONTYPE def; 2240 InitOMXParams(&def); 2241 def.nPortIndex = kPortIndexOutput; 2242 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, 2243 &def, sizeof(def)), OK); 2244 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 2245 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 2246 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, 2247 &def, sizeof(def)), OK); 2248 2249 // profile 2250 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2251 InitOMXParams(&profile); 2252 profile.nPortIndex = kPortIndexOutput; 2253 CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac, 2254 &profile, sizeof(profile)), OK); 2255 profile.nChannels = numChannels; 2256 profile.eChannelMode = (numChannels == 1? 2257 OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo); 2258 profile.nSampleRate = sampleRate; 2259 profile.nBitRate = 96000; // XXX 2260 profile.nAudioBandWidth = 0; 2261 profile.nFrameLength = 0; 2262 profile.nAACtools = OMX_AUDIO_AACToolAll; 2263 profile.nAACERtools = OMX_AUDIO_AACERNone; 2264 profile.eAACProfile = OMX_AUDIO_AACObjectLC; 2265 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 2266 CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac, 2267 &profile, sizeof(profile)), OK); 2268 2269 } else { 2270 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2271 InitOMXParams(&profile); 2272 profile.nPortIndex = kPortIndexInput; 2273 2274 status_t err = mOMX->getParameter( 2275 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2276 CHECK_EQ(err, OK); 2277 2278 profile.nChannels = numChannels; 2279 profile.nSampleRate = sampleRate; 2280 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 2281 2282 err = mOMX->setParameter( 2283 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2284 CHECK_EQ(err, OK); 2285 } 2286} 2287 2288void OMXCodec::setImageOutputFormat( 2289 OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) { 2290 CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height); 2291 2292#if 0 2293 OMX_INDEXTYPE index; 2294 status_t err = mOMX->get_extension_index( 2295 mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index); 2296 CHECK_EQ(err, OK); 2297 2298 err = mOMX->set_config(mNode, index, &format, sizeof(format)); 2299 CHECK_EQ(err, OK); 2300#endif 2301 2302 OMX_PARAM_PORTDEFINITIONTYPE def; 2303 InitOMXParams(&def); 2304 def.nPortIndex = kPortIndexOutput; 2305 2306 status_t err = mOMX->getParameter( 2307 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2308 CHECK_EQ(err, OK); 2309 2310 CHECK_EQ(def.eDomain, OMX_PortDomainImage); 2311 2312 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; 2313 2314 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused); 2315 imageDef->eColorFormat = format; 2316 imageDef->nFrameWidth = width; 2317 imageDef->nFrameHeight = height; 2318 2319 switch (format) { 2320 case OMX_COLOR_FormatYUV420PackedPlanar: 2321 case OMX_COLOR_FormatYUV411Planar: 2322 { 2323 def.nBufferSize = (width * height * 3) / 2; 2324 break; 2325 } 2326 2327 case OMX_COLOR_FormatCbYCrY: 2328 { 2329 def.nBufferSize = width * height * 2; 2330 break; 2331 } 2332 2333 case OMX_COLOR_Format32bitARGB8888: 2334 { 2335 def.nBufferSize = width * height * 4; 2336 break; 2337 } 2338 2339 case OMX_COLOR_Format16bitARGB4444: 2340 case OMX_COLOR_Format16bitARGB1555: 2341 case OMX_COLOR_Format16bitRGB565: 2342 case OMX_COLOR_Format16bitBGR565: 2343 { 2344 def.nBufferSize = width * height * 2; 2345 break; 2346 } 2347 2348 default: 2349 CHECK(!"Should not be here. Unknown color format."); 2350 break; 2351 } 2352 2353 def.nBufferCountActual = def.nBufferCountMin; 2354 2355 err = mOMX->setParameter( 2356 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2357 CHECK_EQ(err, OK); 2358} 2359 2360void OMXCodec::setJPEGInputFormat( 2361 OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) { 2362 OMX_PARAM_PORTDEFINITIONTYPE def; 2363 InitOMXParams(&def); 2364 def.nPortIndex = kPortIndexInput; 2365 2366 status_t err = mOMX->getParameter( 2367 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2368 CHECK_EQ(err, OK); 2369 2370 CHECK_EQ(def.eDomain, OMX_PortDomainImage); 2371 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; 2372 2373 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG); 2374 imageDef->nFrameWidth = width; 2375 imageDef->nFrameHeight = height; 2376 2377 def.nBufferSize = compressedSize; 2378 def.nBufferCountActual = def.nBufferCountMin; 2379 2380 err = mOMX->setParameter( 2381 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2382 CHECK_EQ(err, OK); 2383} 2384 2385void OMXCodec::addCodecSpecificData(const void *data, size_t size) { 2386 CodecSpecificData *specific = 2387 (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1); 2388 2389 specific->mSize = size; 2390 memcpy(specific->mData, data, size); 2391 2392 mCodecSpecificData.push(specific); 2393} 2394 2395void OMXCodec::clearCodecSpecificData() { 2396 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) { 2397 free(mCodecSpecificData.editItemAt(i)); 2398 } 2399 mCodecSpecificData.clear(); 2400 mCodecSpecificDataIndex = 0; 2401} 2402 2403status_t OMXCodec::start(MetaData *) { 2404 Mutex::Autolock autoLock(mLock); 2405 2406 if (mState != LOADED) { 2407 return UNKNOWN_ERROR; 2408 } 2409 2410 sp<MetaData> params = new MetaData; 2411 if (mQuirks & kWantsNALFragments) { 2412 params->setInt32(kKeyWantsNALFragments, true); 2413 } 2414 status_t err = mSource->start(params.get()); 2415 2416 if (err != OK) { 2417 return err; 2418 } 2419 2420 mCodecSpecificDataIndex = 0; 2421 mInitialBufferSubmit = true; 2422 mSignalledEOS = false; 2423 mNoMoreOutputData = false; 2424 mOutputPortSettingsHaveChanged = false; 2425 mSeekTimeUs = -1; 2426 mFilledBuffers.clear(); 2427 2428 return init(); 2429} 2430 2431status_t OMXCodec::stop() { 2432 CODEC_LOGV("stop mState=%d", mState); 2433 2434 Mutex::Autolock autoLock(mLock); 2435 2436 while (isIntermediateState(mState)) { 2437 mAsyncCompletion.wait(mLock); 2438 } 2439 2440 switch (mState) { 2441 case LOADED: 2442 case ERROR: 2443 break; 2444 2445 case EXECUTING: 2446 { 2447 setState(EXECUTING_TO_IDLE); 2448 2449 if (mQuirks & kRequiresFlushBeforeShutdown) { 2450 CODEC_LOGV("This component requires a flush before transitioning " 2451 "from EXECUTING to IDLE..."); 2452 2453 bool emulateInputFlushCompletion = 2454 !flushPortAsync(kPortIndexInput); 2455 2456 bool emulateOutputFlushCompletion = 2457 !flushPortAsync(kPortIndexOutput); 2458 2459 if (emulateInputFlushCompletion) { 2460 onCmdComplete(OMX_CommandFlush, kPortIndexInput); 2461 } 2462 2463 if (emulateOutputFlushCompletion) { 2464 onCmdComplete(OMX_CommandFlush, kPortIndexOutput); 2465 } 2466 } else { 2467 mPortStatus[kPortIndexInput] = SHUTTING_DOWN; 2468 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN; 2469 2470 status_t err = 2471 mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); 2472 CHECK_EQ(err, OK); 2473 } 2474 2475 while (mState != LOADED && mState != ERROR) { 2476 mAsyncCompletion.wait(mLock); 2477 } 2478 2479 break; 2480 } 2481 2482 default: 2483 { 2484 CHECK(!"should not be here."); 2485 break; 2486 } 2487 } 2488 2489 if (mLeftOverBuffer) { 2490 mLeftOverBuffer->release(); 2491 mLeftOverBuffer = NULL; 2492 } 2493 2494 mSource->stop(); 2495 2496 CODEC_LOGV("stopped"); 2497 2498 return OK; 2499} 2500 2501sp<MetaData> OMXCodec::getFormat() { 2502 Mutex::Autolock autoLock(mLock); 2503 2504 return mOutputFormat; 2505} 2506 2507status_t OMXCodec::read( 2508 MediaBuffer **buffer, const ReadOptions *options) { 2509 *buffer = NULL; 2510 2511 Mutex::Autolock autoLock(mLock); 2512 2513 if (mState != EXECUTING && mState != RECONFIGURING) { 2514 return UNKNOWN_ERROR; 2515 } 2516 2517 bool seeking = false; 2518 int64_t seekTimeUs; 2519 if (options && options->getSeekTo(&seekTimeUs)) { 2520 seeking = true; 2521 } 2522 2523 if (mInitialBufferSubmit) { 2524 mInitialBufferSubmit = false; 2525 2526 if (seeking) { 2527 CHECK(seekTimeUs >= 0); 2528 mSeekTimeUs = seekTimeUs; 2529 2530 // There's no reason to trigger the code below, there's 2531 // nothing to flush yet. 2532 seeking = false; 2533 } 2534 2535 drainInputBuffers(); 2536 2537 if (mState == EXECUTING) { 2538 // Otherwise mState == RECONFIGURING and this code will trigger 2539 // after the output port is reenabled. 2540 fillOutputBuffers(); 2541 } 2542 } 2543 2544 if (seeking) { 2545 CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6); 2546 2547 mSignalledEOS = false; 2548 2549 CHECK(seekTimeUs >= 0); 2550 mSeekTimeUs = seekTimeUs; 2551 2552 mFilledBuffers.clear(); 2553 2554 CHECK_EQ(mState, EXECUTING); 2555 2556 bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput); 2557 bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput); 2558 2559 if (emulateInputFlushCompletion) { 2560 onCmdComplete(OMX_CommandFlush, kPortIndexInput); 2561 } 2562 2563 if (emulateOutputFlushCompletion) { 2564 onCmdComplete(OMX_CommandFlush, kPortIndexOutput); 2565 } 2566 2567 while (mSeekTimeUs >= 0) { 2568 mBufferFilled.wait(mLock); 2569 } 2570 } 2571 2572 while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) { 2573 mBufferFilled.wait(mLock); 2574 } 2575 2576 if (mState == ERROR) { 2577 return UNKNOWN_ERROR; 2578 } 2579 2580 if (mFilledBuffers.empty()) { 2581 return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM; 2582 } 2583 2584 if (mOutputPortSettingsHaveChanged) { 2585 mOutputPortSettingsHaveChanged = false; 2586 2587 return INFO_FORMAT_CHANGED; 2588 } 2589 2590 size_t index = *mFilledBuffers.begin(); 2591 mFilledBuffers.erase(mFilledBuffers.begin()); 2592 2593 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 2594 info->mMediaBuffer->add_ref(); 2595 *buffer = info->mMediaBuffer; 2596 2597 return OK; 2598} 2599 2600void OMXCodec::signalBufferReturned(MediaBuffer *buffer) { 2601 Mutex::Autolock autoLock(mLock); 2602 2603 Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput]; 2604 for (size_t i = 0; i < buffers->size(); ++i) { 2605 BufferInfo *info = &buffers->editItemAt(i); 2606 2607 if (info->mMediaBuffer == buffer) { 2608 CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED); 2609 fillOutputBuffer(info); 2610 return; 2611 } 2612 } 2613 2614 CHECK(!"should not be here."); 2615} 2616 2617static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) { 2618 static const char *kNames[] = { 2619 "OMX_IMAGE_CodingUnused", 2620 "OMX_IMAGE_CodingAutoDetect", 2621 "OMX_IMAGE_CodingJPEG", 2622 "OMX_IMAGE_CodingJPEG2K", 2623 "OMX_IMAGE_CodingEXIF", 2624 "OMX_IMAGE_CodingTIFF", 2625 "OMX_IMAGE_CodingGIF", 2626 "OMX_IMAGE_CodingPNG", 2627 "OMX_IMAGE_CodingLZW", 2628 "OMX_IMAGE_CodingBMP", 2629 }; 2630 2631 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 2632 2633 if (type < 0 || (size_t)type >= numNames) { 2634 return "UNKNOWN"; 2635 } else { 2636 return kNames[type]; 2637 } 2638} 2639 2640static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) { 2641 static const char *kNames[] = { 2642 "OMX_COLOR_FormatUnused", 2643 "OMX_COLOR_FormatMonochrome", 2644 "OMX_COLOR_Format8bitRGB332", 2645 "OMX_COLOR_Format12bitRGB444", 2646 "OMX_COLOR_Format16bitARGB4444", 2647 "OMX_COLOR_Format16bitARGB1555", 2648 "OMX_COLOR_Format16bitRGB565", 2649 "OMX_COLOR_Format16bitBGR565", 2650 "OMX_COLOR_Format18bitRGB666", 2651 "OMX_COLOR_Format18bitARGB1665", 2652 "OMX_COLOR_Format19bitARGB1666", 2653 "OMX_COLOR_Format24bitRGB888", 2654 "OMX_COLOR_Format24bitBGR888", 2655 "OMX_COLOR_Format24bitARGB1887", 2656 "OMX_COLOR_Format25bitARGB1888", 2657 "OMX_COLOR_Format32bitBGRA8888", 2658 "OMX_COLOR_Format32bitARGB8888", 2659 "OMX_COLOR_FormatYUV411Planar", 2660 "OMX_COLOR_FormatYUV411PackedPlanar", 2661 "OMX_COLOR_FormatYUV420Planar", 2662 "OMX_COLOR_FormatYUV420PackedPlanar", 2663 "OMX_COLOR_FormatYUV420SemiPlanar", 2664 "OMX_COLOR_FormatYUV422Planar", 2665 "OMX_COLOR_FormatYUV422PackedPlanar", 2666 "OMX_COLOR_FormatYUV422SemiPlanar", 2667 "OMX_COLOR_FormatYCbYCr", 2668 "OMX_COLOR_FormatYCrYCb", 2669 "OMX_COLOR_FormatCbYCrY", 2670 "OMX_COLOR_FormatCrYCbY", 2671 "OMX_COLOR_FormatYUV444Interleaved", 2672 "OMX_COLOR_FormatRawBayer8bit", 2673 "OMX_COLOR_FormatRawBayer10bit", 2674 "OMX_COLOR_FormatRawBayer8bitcompressed", 2675 "OMX_COLOR_FormatL2", 2676 "OMX_COLOR_FormatL4", 2677 "OMX_COLOR_FormatL8", 2678 "OMX_COLOR_FormatL16", 2679 "OMX_COLOR_FormatL24", 2680 "OMX_COLOR_FormatL32", 2681 "OMX_COLOR_FormatYUV420PackedSemiPlanar", 2682 "OMX_COLOR_FormatYUV422PackedSemiPlanar", 2683 "OMX_COLOR_Format18BitBGR666", 2684 "OMX_COLOR_Format24BitARGB6666", 2685 "OMX_COLOR_Format24BitABGR6666", 2686 }; 2687 2688 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 2689 2690 if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) { 2691 return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar"; 2692 } else if (type < 0 || (size_t)type >= numNames) { 2693 return "UNKNOWN"; 2694 } else { 2695 return kNames[type]; 2696 } 2697} 2698 2699static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) { 2700 static const char *kNames[] = { 2701 "OMX_VIDEO_CodingUnused", 2702 "OMX_VIDEO_CodingAutoDetect", 2703 "OMX_VIDEO_CodingMPEG2", 2704 "OMX_VIDEO_CodingH263", 2705 "OMX_VIDEO_CodingMPEG4", 2706 "OMX_VIDEO_CodingWMV", 2707 "OMX_VIDEO_CodingRV", 2708 "OMX_VIDEO_CodingAVC", 2709 "OMX_VIDEO_CodingMJPEG", 2710 }; 2711 2712 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 2713 2714 if (type < 0 || (size_t)type >= numNames) { 2715 return "UNKNOWN"; 2716 } else { 2717 return kNames[type]; 2718 } 2719} 2720 2721static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) { 2722 static const char *kNames[] = { 2723 "OMX_AUDIO_CodingUnused", 2724 "OMX_AUDIO_CodingAutoDetect", 2725 "OMX_AUDIO_CodingPCM", 2726 "OMX_AUDIO_CodingADPCM", 2727 "OMX_AUDIO_CodingAMR", 2728 "OMX_AUDIO_CodingGSMFR", 2729 "OMX_AUDIO_CodingGSMEFR", 2730 "OMX_AUDIO_CodingGSMHR", 2731 "OMX_AUDIO_CodingPDCFR", 2732 "OMX_AUDIO_CodingPDCEFR", 2733 "OMX_AUDIO_CodingPDCHR", 2734 "OMX_AUDIO_CodingTDMAFR", 2735 "OMX_AUDIO_CodingTDMAEFR", 2736 "OMX_AUDIO_CodingQCELP8", 2737 "OMX_AUDIO_CodingQCELP13", 2738 "OMX_AUDIO_CodingEVRC", 2739 "OMX_AUDIO_CodingSMV", 2740 "OMX_AUDIO_CodingG711", 2741 "OMX_AUDIO_CodingG723", 2742 "OMX_AUDIO_CodingG726", 2743 "OMX_AUDIO_CodingG729", 2744 "OMX_AUDIO_CodingAAC", 2745 "OMX_AUDIO_CodingMP3", 2746 "OMX_AUDIO_CodingSBC", 2747 "OMX_AUDIO_CodingVORBIS", 2748 "OMX_AUDIO_CodingWMA", 2749 "OMX_AUDIO_CodingRA", 2750 "OMX_AUDIO_CodingMIDI", 2751 }; 2752 2753 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 2754 2755 if (type < 0 || (size_t)type >= numNames) { 2756 return "UNKNOWN"; 2757 } else { 2758 return kNames[type]; 2759 } 2760} 2761 2762static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) { 2763 static const char *kNames[] = { 2764 "OMX_AUDIO_PCMModeLinear", 2765 "OMX_AUDIO_PCMModeALaw", 2766 "OMX_AUDIO_PCMModeMULaw", 2767 }; 2768 2769 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 2770 2771 if (type < 0 || (size_t)type >= numNames) { 2772 return "UNKNOWN"; 2773 } else { 2774 return kNames[type]; 2775 } 2776} 2777 2778static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) { 2779 static const char *kNames[] = { 2780 "OMX_AUDIO_AMRBandModeUnused", 2781 "OMX_AUDIO_AMRBandModeNB0", 2782 "OMX_AUDIO_AMRBandModeNB1", 2783 "OMX_AUDIO_AMRBandModeNB2", 2784 "OMX_AUDIO_AMRBandModeNB3", 2785 "OMX_AUDIO_AMRBandModeNB4", 2786 "OMX_AUDIO_AMRBandModeNB5", 2787 "OMX_AUDIO_AMRBandModeNB6", 2788 "OMX_AUDIO_AMRBandModeNB7", 2789 "OMX_AUDIO_AMRBandModeWB0", 2790 "OMX_AUDIO_AMRBandModeWB1", 2791 "OMX_AUDIO_AMRBandModeWB2", 2792 "OMX_AUDIO_AMRBandModeWB3", 2793 "OMX_AUDIO_AMRBandModeWB4", 2794 "OMX_AUDIO_AMRBandModeWB5", 2795 "OMX_AUDIO_AMRBandModeWB6", 2796 "OMX_AUDIO_AMRBandModeWB7", 2797 "OMX_AUDIO_AMRBandModeWB8", 2798 }; 2799 2800 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 2801 2802 if (type < 0 || (size_t)type >= numNames) { 2803 return "UNKNOWN"; 2804 } else { 2805 return kNames[type]; 2806 } 2807} 2808 2809static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) { 2810 static const char *kNames[] = { 2811 "OMX_AUDIO_AMRFrameFormatConformance", 2812 "OMX_AUDIO_AMRFrameFormatIF1", 2813 "OMX_AUDIO_AMRFrameFormatIF2", 2814 "OMX_AUDIO_AMRFrameFormatFSF", 2815 "OMX_AUDIO_AMRFrameFormatRTPPayload", 2816 "OMX_AUDIO_AMRFrameFormatITU", 2817 }; 2818 2819 size_t numNames = sizeof(kNames) / sizeof(kNames[0]); 2820 2821 if (type < 0 || (size_t)type >= numNames) { 2822 return "UNKNOWN"; 2823 } else { 2824 return kNames[type]; 2825 } 2826} 2827 2828void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { 2829 OMX_PARAM_PORTDEFINITIONTYPE def; 2830 InitOMXParams(&def); 2831 def.nPortIndex = portIndex; 2832 2833 status_t err = mOMX->getParameter( 2834 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2835 CHECK_EQ(err, OK); 2836 2837 printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output"); 2838 2839 CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput) 2840 || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput)); 2841 2842 printf(" nBufferCountActual = %ld\n", def.nBufferCountActual); 2843 printf(" nBufferCountMin = %ld\n", def.nBufferCountMin); 2844 printf(" nBufferSize = %ld\n", def.nBufferSize); 2845 2846 switch (def.eDomain) { 2847 case OMX_PortDomainImage: 2848 { 2849 const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; 2850 2851 printf("\n"); 2852 printf(" // Image\n"); 2853 printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth); 2854 printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight); 2855 printf(" nStride = %ld\n", imageDef->nStride); 2856 2857 printf(" eCompressionFormat = %s\n", 2858 imageCompressionFormatString(imageDef->eCompressionFormat)); 2859 2860 printf(" eColorFormat = %s\n", 2861 colorFormatString(imageDef->eColorFormat)); 2862 2863 break; 2864 } 2865 2866 case OMX_PortDomainVideo: 2867 { 2868 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 2869 2870 printf("\n"); 2871 printf(" // Video\n"); 2872 printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth); 2873 printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight); 2874 printf(" nStride = %ld\n", videoDef->nStride); 2875 2876 printf(" eCompressionFormat = %s\n", 2877 videoCompressionFormatString(videoDef->eCompressionFormat)); 2878 2879 printf(" eColorFormat = %s\n", 2880 colorFormatString(videoDef->eColorFormat)); 2881 2882 break; 2883 } 2884 2885 case OMX_PortDomainAudio: 2886 { 2887 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 2888 2889 printf("\n"); 2890 printf(" // Audio\n"); 2891 printf(" eEncoding = %s\n", 2892 audioCodingTypeString(audioDef->eEncoding)); 2893 2894 if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) { 2895 OMX_AUDIO_PARAM_PCMMODETYPE params; 2896 InitOMXParams(¶ms); 2897 params.nPortIndex = portIndex; 2898 2899 err = mOMX->getParameter( 2900 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 2901 CHECK_EQ(err, OK); 2902 2903 printf(" nSamplingRate = %ld\n", params.nSamplingRate); 2904 printf(" nChannels = %ld\n", params.nChannels); 2905 printf(" bInterleaved = %d\n", params.bInterleaved); 2906 printf(" nBitPerSample = %ld\n", params.nBitPerSample); 2907 2908 printf(" eNumData = %s\n", 2909 params.eNumData == OMX_NumericalDataSigned 2910 ? "signed" : "unsigned"); 2911 2912 printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode)); 2913 } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) { 2914 OMX_AUDIO_PARAM_AMRTYPE amr; 2915 InitOMXParams(&amr); 2916 amr.nPortIndex = portIndex; 2917 2918 err = mOMX->getParameter( 2919 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr)); 2920 CHECK_EQ(err, OK); 2921 2922 printf(" nChannels = %ld\n", amr.nChannels); 2923 printf(" eAMRBandMode = %s\n", 2924 amrBandModeString(amr.eAMRBandMode)); 2925 printf(" eAMRFrameFormat = %s\n", 2926 amrFrameFormatString(amr.eAMRFrameFormat)); 2927 } 2928 2929 break; 2930 } 2931 2932 default: 2933 { 2934 printf(" // Unknown\n"); 2935 break; 2936 } 2937 } 2938 2939 printf("}\n"); 2940} 2941 2942void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { 2943 mOutputFormat = new MetaData; 2944 mOutputFormat->setCString(kKeyDecoderComponent, mComponentName); 2945 2946 OMX_PARAM_PORTDEFINITIONTYPE def; 2947 InitOMXParams(&def); 2948 def.nPortIndex = kPortIndexOutput; 2949 2950 status_t err = mOMX->getParameter( 2951 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2952 CHECK_EQ(err, OK); 2953 2954 switch (def.eDomain) { 2955 case OMX_PortDomainImage: 2956 { 2957 OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image; 2958 CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused); 2959 2960 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 2961 mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat); 2962 mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth); 2963 mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight); 2964 break; 2965 } 2966 2967 case OMX_PortDomainAudio: 2968 { 2969 OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio; 2970 2971 if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) { 2972 OMX_AUDIO_PARAM_PCMMODETYPE params; 2973 InitOMXParams(¶ms); 2974 params.nPortIndex = kPortIndexOutput; 2975 2976 err = mOMX->getParameter( 2977 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 2978 CHECK_EQ(err, OK); 2979 2980 CHECK_EQ(params.eNumData, OMX_NumericalDataSigned); 2981 CHECK_EQ(params.nBitPerSample, 16); 2982 CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear); 2983 2984 int32_t numChannels, sampleRate; 2985 inputFormat->findInt32(kKeyChannelCount, &numChannels); 2986 inputFormat->findInt32(kKeySampleRate, &sampleRate); 2987 2988 if ((OMX_U32)numChannels != params.nChannels) { 2989 LOGW("Codec outputs a different number of channels than " 2990 "the input stream contains (contains %d channels, " 2991 "codec outputs %ld channels).", 2992 numChannels, params.nChannels); 2993 } 2994 2995 mOutputFormat->setCString( 2996 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 2997 2998 // Use the codec-advertised number of channels, as some 2999 // codecs appear to output stereo even if the input data is 3000 // mono. If we know the codec lies about this information, 3001 // use the actual number of channels instead. 3002 mOutputFormat->setInt32( 3003 kKeyChannelCount, 3004 (mQuirks & kDecoderLiesAboutNumberOfChannels) 3005 ? numChannels : params.nChannels); 3006 3007 // The codec-reported sampleRate is not reliable... 3008 mOutputFormat->setInt32(kKeySampleRate, sampleRate); 3009 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) { 3010 OMX_AUDIO_PARAM_AMRTYPE amr; 3011 InitOMXParams(&amr); 3012 amr.nPortIndex = kPortIndexOutput; 3013 3014 err = mOMX->getParameter( 3015 mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr)); 3016 CHECK_EQ(err, OK); 3017 3018 CHECK_EQ(amr.nChannels, 1); 3019 mOutputFormat->setInt32(kKeyChannelCount, 1); 3020 3021 if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0 3022 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) { 3023 mOutputFormat->setCString( 3024 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB); 3025 mOutputFormat->setInt32(kKeySampleRate, 8000); 3026 } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0 3027 && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) { 3028 mOutputFormat->setCString( 3029 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB); 3030 mOutputFormat->setInt32(kKeySampleRate, 16000); 3031 } else { 3032 CHECK(!"Unknown AMR band mode."); 3033 } 3034 } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) { 3035 mOutputFormat->setCString( 3036 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 3037 int32_t numChannels, sampleRate; 3038 inputFormat->findInt32(kKeyChannelCount, &numChannels); 3039 inputFormat->findInt32(kKeySampleRate, &sampleRate); 3040 mOutputFormat->setInt32(kKeyChannelCount, numChannels); 3041 mOutputFormat->setInt32(kKeySampleRate, sampleRate); 3042 } else { 3043 CHECK(!"Should not be here. Unknown audio encoding."); 3044 } 3045 break; 3046 } 3047 3048 case OMX_PortDomainVideo: 3049 { 3050 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 3051 3052 if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) { 3053 mOutputFormat->setCString( 3054 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 3055 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) { 3056 mOutputFormat->setCString( 3057 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 3058 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) { 3059 mOutputFormat->setCString( 3060 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); 3061 } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) { 3062 mOutputFormat->setCString( 3063 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 3064 } else { 3065 CHECK(!"Unknown compression format."); 3066 } 3067 3068 if (!strcmp(mComponentName, "OMX.PV.avcdec")) { 3069 // This component appears to be lying to me. 3070 mOutputFormat->setInt32( 3071 kKeyWidth, (video_def->nFrameWidth + 15) & -16); 3072 mOutputFormat->setInt32( 3073 kKeyHeight, (video_def->nFrameHeight + 15) & -16); 3074 } else { 3075 mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth); 3076 mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight); 3077 } 3078 3079 mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat); 3080 break; 3081 } 3082 3083 default: 3084 { 3085 CHECK(!"should not be here, neither audio nor video."); 3086 break; 3087 } 3088 } 3089} 3090 3091//////////////////////////////////////////////////////////////////////////////// 3092 3093status_t QueryCodecs( 3094 const sp<IOMX> &omx, 3095 const char *mime, bool queryDecoders, 3096 Vector<CodecCapabilities> *results) { 3097 results->clear(); 3098 3099 for (int index = 0;; ++index) { 3100 const char *componentName; 3101 3102 if (!queryDecoders) { 3103 componentName = GetCodec( 3104 kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]), 3105 mime, index); 3106 } else { 3107 componentName = GetCodec( 3108 kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]), 3109 mime, index); 3110 } 3111 3112 if (!componentName) { 3113 return OK; 3114 } 3115 3116 if (strncmp(componentName, "OMX.", 4)) { 3117 // Not an OpenMax component but a software codec. 3118 3119 results->push(); 3120 CodecCapabilities *caps = &results->editItemAt(results->size() - 1); 3121 caps->mComponentName = componentName; 3122 3123 continue; 3124 } 3125 3126 sp<OMXCodecObserver> observer = new OMXCodecObserver; 3127 IOMX::node_id node; 3128 status_t err = omx->allocateNode(componentName, observer, &node); 3129 3130 if (err != OK) { 3131 continue; 3132 } 3133 3134 OMXCodec::setComponentRole(omx, node, !queryDecoders, mime); 3135 3136 results->push(); 3137 CodecCapabilities *caps = &results->editItemAt(results->size() - 1); 3138 caps->mComponentName = componentName; 3139 3140 OMX_VIDEO_PARAM_PROFILELEVELTYPE param; 3141 InitOMXParams(¶m); 3142 3143 param.nPortIndex = queryDecoders ? 0 : 1; 3144 3145 for (param.nProfileIndex = 0;; ++param.nProfileIndex) { 3146 err = omx->getParameter( 3147 node, OMX_IndexParamVideoProfileLevelQuerySupported, 3148 ¶m, sizeof(param)); 3149 3150 if (err != OK) { 3151 break; 3152 } 3153 3154 CodecProfileLevel profileLevel; 3155 profileLevel.mProfile = param.eProfile; 3156 profileLevel.mLevel = param.eLevel; 3157 3158 caps->mProfileLevels.push(profileLevel); 3159 } 3160 3161 CHECK_EQ(omx->freeNode(node), OK); 3162 } 3163} 3164 3165} // namespace android 3166