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