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