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