stagefright.cpp revision 515e855eae78aa495da58356486aaa666cb57fd1
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 "stagefright" 19#include <media/stagefright/foundation/ADebug.h> 20 21#include <sys/time.h> 22 23#include <stdlib.h> 24#include <string.h> 25#include <unistd.h> 26 27#include "SineSource.h" 28 29#include <binder/IServiceManager.h> 30#include <binder/ProcessState.h> 31#include <media/IMediaPlayerService.h> 32#include <media/stagefright/foundation/ALooper.h> 33#include "include/ARTSPController.h" 34#include "include/LiveSession.h" 35#include "include/NuCachedSource2.h" 36#include <media/stagefright/AudioPlayer.h> 37#include <media/stagefright/DataSource.h> 38#include <media/stagefright/JPEGSource.h> 39#include <media/stagefright/MediaDefs.h> 40#include <media/stagefright/MediaErrors.h> 41#include <media/stagefright/MediaExtractor.h> 42#include <media/stagefright/MediaSource.h> 43#include <media/stagefright/MetaData.h> 44#include <media/stagefright/OMXClient.h> 45#include <media/stagefright/OMXCodec.h> 46#include <media/mediametadataretriever.h> 47 48#include <media/stagefright/foundation/hexdump.h> 49#include <media/stagefright/MPEG2TSWriter.h> 50#include <media/stagefright/MPEG4Writer.h> 51 52#include <private/media/VideoFrame.h> 53#include <SkBitmap.h> 54#include <SkImageEncoder.h> 55 56#include <fcntl.h> 57 58#include <gui/SurfaceTextureClient.h> 59 60#include <surfaceflinger/ISurfaceComposer.h> 61#include <surfaceflinger/SurfaceComposerClient.h> 62 63using namespace android; 64 65static long gNumRepetitions; 66static long gMaxNumFrames; // 0 means decode all available. 67static long gReproduceBug; // if not -1. 68static bool gPreferSoftwareCodec; 69static bool gPlaybackAudio; 70static bool gWriteMP4; 71static bool gDisplayHistogram; 72static String8 gWriteMP4Filename; 73 74static sp<ANativeWindow> gSurface; 75 76#define USE_SURFACE_COMPOSER 0 77 78static int64_t getNowUs() { 79 struct timeval tv; 80 gettimeofday(&tv, NULL); 81 82 return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll; 83} 84 85static int CompareIncreasing(const int64_t *a, const int64_t *b) { 86 return (*a) < (*b) ? -1 : (*a) > (*b) ? 1 : 0; 87} 88 89static void displayDecodeHistogram(Vector<int64_t> *decodeTimesUs) { 90 printf("decode times:\n"); 91 92 decodeTimesUs->sort(CompareIncreasing); 93 94 size_t n = decodeTimesUs->size(); 95 int64_t minUs = decodeTimesUs->itemAt(0); 96 int64_t maxUs = decodeTimesUs->itemAt(n - 1); 97 98 printf("min decode time %lld us (%.2f secs)\n", minUs, minUs / 1E6); 99 printf("max decode time %lld us (%.2f secs)\n", maxUs, maxUs / 1E6); 100 101 size_t counts[100]; 102 for (size_t i = 0; i < 100; ++i) { 103 counts[i] = 0; 104 } 105 106 for (size_t i = 0; i < n; ++i) { 107 int64_t x = decodeTimesUs->itemAt(i); 108 109 size_t slot = ((x - minUs) * 100) / (maxUs - minUs); 110 if (slot == 100) { slot = 99; } 111 112 ++counts[slot]; 113 } 114 115 for (size_t i = 0; i < 100; ++i) { 116 int64_t slotUs = minUs + (i * (maxUs - minUs) / 100); 117 118 double fps = 1E6 / slotUs; 119 printf("[%.2f fps]: %d\n", fps, counts[i]); 120 } 121} 122 123static void displayAVCProfileLevelIfPossible(const sp<MetaData>& meta) { 124 uint32_t type; 125 const void *data; 126 size_t size; 127 if (meta->findData(kKeyAVCC, &type, &data, &size)) { 128 const uint8_t *ptr = (const uint8_t *)data; 129 CHECK(size >= 7); 130 CHECK(ptr[0] == 1); // configurationVersion == 1 131 uint8_t profile = ptr[1]; 132 uint8_t level = ptr[3]; 133 fprintf(stderr, "AVC video profile %d and level %d\n", profile, level); 134 } 135} 136 137static void playSource(OMXClient *client, sp<MediaSource> &source) { 138 sp<MetaData> meta = source->getFormat(); 139 140 const char *mime; 141 CHECK(meta->findCString(kKeyMIMEType, &mime)); 142 143 sp<MediaSource> rawSource; 144 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) { 145 rawSource = source; 146 } else { 147 rawSource = OMXCodec::Create( 148 client->interface(), meta, false /* createEncoder */, source, 149 NULL /* matchComponentName */, 150 gPreferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0, 151 gSurface); 152 153 if (rawSource == NULL) { 154 fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime); 155 return; 156 } 157 displayAVCProfileLevelIfPossible(meta); 158 } 159 160 source.clear(); 161 162 status_t err = rawSource->start(); 163 164 if (err != OK) { 165 fprintf(stderr, "rawSource returned error %d (0x%08x)\n", err, err); 166 return; 167 } 168 169 if (gPlaybackAudio) { 170 AudioPlayer *player = new AudioPlayer(NULL); 171 player->setSource(rawSource); 172 rawSource.clear(); 173 174 player->start(true /* sourceAlreadyStarted */); 175 176 status_t finalStatus; 177 while (!player->reachedEOS(&finalStatus)) { 178 usleep(100000ll); 179 } 180 181 delete player; 182 player = NULL; 183 184 return; 185 } else if (gReproduceBug >= 3 && gReproduceBug <= 5) { 186 int64_t durationUs; 187 CHECK(meta->findInt64(kKeyDuration, &durationUs)); 188 189 status_t err; 190 MediaBuffer *buffer; 191 MediaSource::ReadOptions options; 192 int64_t seekTimeUs = -1; 193 for (;;) { 194 err = rawSource->read(&buffer, &options); 195 options.clearSeekTo(); 196 197 bool shouldSeek = false; 198 if (err == INFO_FORMAT_CHANGED) { 199 CHECK(buffer == NULL); 200 201 printf("format changed.\n"); 202 continue; 203 } else if (err != OK) { 204 printf("reached EOF.\n"); 205 206 shouldSeek = true; 207 } else { 208 int64_t timestampUs; 209 CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 210 211 bool failed = false; 212 213 if (seekTimeUs >= 0) { 214 int64_t diff = timestampUs - seekTimeUs; 215 216 if (diff < 0) { 217 diff = -diff; 218 } 219 220 if ((gReproduceBug == 4 && diff > 500000) 221 || (gReproduceBug == 5 && timestampUs < 0)) { 222 printf("wanted: %.2f secs, got: %.2f secs\n", 223 seekTimeUs / 1E6, timestampUs / 1E6); 224 225 printf("ERROR: "); 226 failed = true; 227 } 228 } 229 230 printf("buffer has timestamp %lld us (%.2f secs)\n", 231 timestampUs, timestampUs / 1E6); 232 233 buffer->release(); 234 buffer = NULL; 235 236 if (failed) { 237 break; 238 } 239 240 shouldSeek = ((double)rand() / RAND_MAX) < 0.1; 241 242 if (gReproduceBug == 3) { 243 shouldSeek = false; 244 } 245 } 246 247 seekTimeUs = -1; 248 249 if (shouldSeek) { 250 seekTimeUs = (rand() * (float)durationUs) / RAND_MAX; 251 options.setSeekTo(seekTimeUs); 252 253 printf("seeking to %lld us (%.2f secs)\n", 254 seekTimeUs, seekTimeUs / 1E6); 255 } 256 } 257 258 rawSource->stop(); 259 260 return; 261 } 262 263 int n = 0; 264 int64_t startTime = getNowUs(); 265 266 long numIterationsLeft = gNumRepetitions; 267 MediaSource::ReadOptions options; 268 269 int64_t sumDecodeUs = 0; 270 int64_t totalBytes = 0; 271 272 Vector<int64_t> decodeTimesUs; 273 274 while (numIterationsLeft-- > 0) { 275 long numFrames = 0; 276 277 MediaBuffer *buffer; 278 279 for (;;) { 280 int64_t startDecodeUs = getNowUs(); 281 status_t err = rawSource->read(&buffer, &options); 282 int64_t delayDecodeUs = getNowUs() - startDecodeUs; 283 284 options.clearSeekTo(); 285 286 if (err != OK) { 287 CHECK(buffer == NULL); 288 289 if (err == INFO_FORMAT_CHANGED) { 290 printf("format changed.\n"); 291 continue; 292 } 293 294 break; 295 } 296 297 if (buffer->range_length() > 0) { 298 if (gDisplayHistogram && n > 0) { 299 // Ignore the first time since it includes some setup 300 // cost. 301 decodeTimesUs.push(delayDecodeUs); 302 } 303 304 if ((n++ % 16) == 0) { 305 printf("."); 306 fflush(stdout); 307 } 308 } 309 310 sumDecodeUs += delayDecodeUs; 311 totalBytes += buffer->range_length(); 312 313 buffer->release(); 314 buffer = NULL; 315 316 ++numFrames; 317 if (gMaxNumFrames > 0 && numFrames == gMaxNumFrames) { 318 break; 319 } 320 321 if (gReproduceBug == 1 && numFrames == 40) { 322 printf("seeking past the end now."); 323 options.setSeekTo(0x7fffffffL); 324 } else if (gReproduceBug == 2 && numFrames == 40) { 325 printf("seeking to 5 secs."); 326 options.setSeekTo(5000000); 327 } 328 } 329 330 printf("$"); 331 fflush(stdout); 332 333 options.setSeekTo(0); 334 } 335 336 rawSource->stop(); 337 printf("\n"); 338 339 int64_t delay = getNowUs() - startTime; 340 if (!strncasecmp("video/", mime, 6)) { 341 printf("avg. %.2f fps\n", n * 1E6 / delay); 342 343 printf("avg. time to decode one buffer %.2f usecs\n", 344 (double)sumDecodeUs / n); 345 346 printf("decoded a total of %d frame(s).\n", n); 347 348 if (gDisplayHistogram) { 349 displayDecodeHistogram(&decodeTimesUs); 350 } 351 } else if (!strncasecmp("audio/", mime, 6)) { 352 // Frame count makes less sense for audio, as the output buffer 353 // sizes may be different across decoders. 354 printf("avg. %.2f KB/sec\n", totalBytes / 1024 * 1E6 / delay); 355 356 printf("decoded a total of %lld bytes\n", totalBytes); 357 } 358} 359 360//////////////////////////////////////////////////////////////////////////////// 361 362struct DetectSyncSource : public MediaSource { 363 DetectSyncSource(const sp<MediaSource> &source); 364 365 virtual status_t start(MetaData *params = NULL); 366 virtual status_t stop(); 367 virtual sp<MetaData> getFormat(); 368 369 virtual status_t read( 370 MediaBuffer **buffer, const ReadOptions *options); 371 372private: 373 enum StreamType { 374 AVC, 375 MPEG4, 376 H263, 377 OTHER, 378 }; 379 380 sp<MediaSource> mSource; 381 StreamType mStreamType; 382 383 DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource); 384}; 385 386DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source) 387 : mSource(source), 388 mStreamType(OTHER) { 389 const char *mime; 390 CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); 391 392 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 393 mStreamType = AVC; 394 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) { 395 mStreamType = MPEG4; 396 CHECK(!"sync frame detection not implemented yet for MPEG4"); 397 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) { 398 mStreamType = H263; 399 CHECK(!"sync frame detection not implemented yet for H.263"); 400 } 401} 402 403status_t DetectSyncSource::start(MetaData *params) { 404 return mSource->start(params); 405} 406 407status_t DetectSyncSource::stop() { 408 return mSource->stop(); 409} 410 411sp<MetaData> DetectSyncSource::getFormat() { 412 return mSource->getFormat(); 413} 414 415static bool isIDRFrame(MediaBuffer *buffer) { 416 const uint8_t *data = 417 (const uint8_t *)buffer->data() + buffer->range_offset(); 418 size_t size = buffer->range_length(); 419 for (size_t i = 0; i + 3 < size; ++i) { 420 if (!memcmp("\x00\x00\x01", &data[i], 3)) { 421 uint8_t nalType = data[i + 3] & 0x1f; 422 if (nalType == 5) { 423 return true; 424 } 425 } 426 } 427 428 return false; 429} 430 431status_t DetectSyncSource::read( 432 MediaBuffer **buffer, const ReadOptions *options) { 433 status_t err = mSource->read(buffer, options); 434 435 if (err != OK) { 436 return err; 437 } 438 439 if (mStreamType == AVC && isIDRFrame(*buffer)) { 440 (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true); 441 } else { 442 (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true); 443 } 444 445 return OK; 446} 447 448//////////////////////////////////////////////////////////////////////////////// 449 450static void writeSourcesToMP4( 451 Vector<sp<MediaSource> > &sources, bool syncInfoPresent) { 452#if 0 453 sp<MPEG4Writer> writer = 454 new MPEG4Writer(gWriteMP4Filename.string()); 455#else 456 sp<MPEG2TSWriter> writer = 457 new MPEG2TSWriter(gWriteMP4Filename.string()); 458#endif 459 460 // at most one minute. 461 writer->setMaxFileDuration(60000000ll); 462 463 for (size_t i = 0; i < sources.size(); ++i) { 464 sp<MediaSource> source = sources.editItemAt(i); 465 466 CHECK_EQ(writer->addSource( 467 syncInfoPresent ? source : new DetectSyncSource(source)), 468 (status_t)OK); 469 } 470 471 sp<MetaData> params = new MetaData; 472 params->setInt32(kKeyNotRealTime, true); 473 CHECK_EQ(writer->start(params.get()), (status_t)OK); 474 475 while (!writer->reachedEOS()) { 476 usleep(100000); 477 } 478 writer->stop(); 479} 480 481static void performSeekTest(const sp<MediaSource> &source) { 482 CHECK_EQ((status_t)OK, source->start()); 483 484 int64_t durationUs; 485 CHECK(source->getFormat()->findInt64(kKeyDuration, &durationUs)); 486 487 for (int64_t seekTimeUs = 0; seekTimeUs <= durationUs; 488 seekTimeUs += 60000ll) { 489 MediaSource::ReadOptions options; 490 options.setSeekTo( 491 seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); 492 493 MediaBuffer *buffer; 494 status_t err; 495 for (;;) { 496 err = source->read(&buffer, &options); 497 498 options.clearSeekTo(); 499 500 if (err == INFO_FORMAT_CHANGED) { 501 CHECK(buffer == NULL); 502 continue; 503 } 504 505 if (err != OK) { 506 CHECK(buffer == NULL); 507 break; 508 } 509 510 if (buffer->range_length() > 0) { 511 break; 512 } 513 514 CHECK(buffer != NULL); 515 516 buffer->release(); 517 buffer = NULL; 518 } 519 520 if (err == OK) { 521 int64_t timeUs; 522 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 523 524 printf("%lld\t%lld\t%lld\n", seekTimeUs, timeUs, seekTimeUs - timeUs); 525 526 buffer->release(); 527 buffer = NULL; 528 } else { 529 printf("ERROR\n"); 530 break; 531 } 532 } 533 534 CHECK_EQ((status_t)OK, source->stop()); 535} 536 537static void usage(const char *me) { 538 fprintf(stderr, "usage: %s\n", me); 539 fprintf(stderr, " -h(elp)\n"); 540 fprintf(stderr, " -a(udio)\n"); 541 fprintf(stderr, " -n repetitions\n"); 542 fprintf(stderr, " -l(ist) components\n"); 543 fprintf(stderr, " -m max-number-of-frames-to-decode in each pass\n"); 544 fprintf(stderr, " -b bug to reproduce\n"); 545 fprintf(stderr, " -p(rofiles) dump decoder profiles supported\n"); 546 fprintf(stderr, " -t(humbnail) extract video thumbnail or album art\n"); 547 fprintf(stderr, " -s(oftware) prefer software codec\n"); 548 fprintf(stderr, " -o playback audio\n"); 549 fprintf(stderr, " -w(rite) filename (write to .mp4 file)\n"); 550 fprintf(stderr, " -k seek test\n"); 551 fprintf(stderr, " -x display a histogram of decoding times/fps " 552 "(video only)\n"); 553 fprintf(stderr, " -S allocate buffers from a surface\n"); 554} 555 556int main(int argc, char **argv) { 557 android::ProcessState::self()->startThreadPool(); 558 559 bool audioOnly = false; 560 bool listComponents = false; 561 bool dumpProfiles = false; 562 bool extractThumbnail = false; 563 bool seekTest = false; 564 bool useSurfaceAlloc = false; 565 gNumRepetitions = 1; 566 gMaxNumFrames = 0; 567 gReproduceBug = -1; 568 gPreferSoftwareCodec = false; 569 gPlaybackAudio = false; 570 gWriteMP4 = false; 571 gDisplayHistogram = false; 572 573 sp<ALooper> looper; 574 sp<ARTSPController> rtspController; 575 sp<LiveSession> liveSession; 576 577 int res; 578 while ((res = getopt(argc, argv, "han:lm:b:ptsow:kxS")) >= 0) { 579 switch (res) { 580 case 'a': 581 { 582 audioOnly = true; 583 break; 584 } 585 586 case 'l': 587 { 588 listComponents = true; 589 break; 590 } 591 592 case 'm': 593 case 'n': 594 case 'b': 595 { 596 char *end; 597 long x = strtol(optarg, &end, 10); 598 599 if (*end != '\0' || end == optarg || x <= 0) { 600 x = 1; 601 } 602 603 if (res == 'n') { 604 gNumRepetitions = x; 605 } else if (res == 'm') { 606 gMaxNumFrames = x; 607 } else { 608 CHECK_EQ(res, 'b'); 609 gReproduceBug = x; 610 } 611 break; 612 } 613 614 case 'w': 615 { 616 gWriteMP4 = true; 617 gWriteMP4Filename.setTo(optarg); 618 break; 619 } 620 621 case 'p': 622 { 623 dumpProfiles = true; 624 break; 625 } 626 627 case 't': 628 { 629 extractThumbnail = true; 630 break; 631 } 632 633 case 's': 634 { 635 gPreferSoftwareCodec = true; 636 break; 637 } 638 639 case 'o': 640 { 641 gPlaybackAudio = true; 642 break; 643 } 644 645 case 'k': 646 { 647 seekTest = true; 648 break; 649 } 650 651 case 'x': 652 { 653 gDisplayHistogram = true; 654 break; 655 } 656 657 case 'S': 658 { 659 useSurfaceAlloc = true; 660 break; 661 } 662 663 case '?': 664 case 'h': 665 default: 666 { 667 usage(argv[0]); 668 exit(1); 669 break; 670 } 671 } 672 } 673 674 if (gPlaybackAudio && !audioOnly) { 675 // This doesn't make any sense if we're decoding the video track. 676 gPlaybackAudio = false; 677 } 678 679 argc -= optind; 680 argv += optind; 681 682 if (extractThumbnail) { 683 sp<IServiceManager> sm = defaultServiceManager(); 684 sp<IBinder> binder = sm->getService(String16("media.player")); 685 sp<IMediaPlayerService> service = 686 interface_cast<IMediaPlayerService>(binder); 687 688 CHECK(service.get() != NULL); 689 690 sp<IMediaMetadataRetriever> retriever = 691 service->createMetadataRetriever(getpid()); 692 693 CHECK(retriever != NULL); 694 695 for (int k = 0; k < argc; ++k) { 696 const char *filename = argv[k]; 697 698 bool failed = true; 699 CHECK_EQ(retriever->setDataSource(filename), (status_t)OK); 700 sp<IMemory> mem = 701 retriever->getFrameAtTime(-1, 702 MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); 703 704 if (mem != NULL) { 705 failed = false; 706 printf("getFrameAtTime(%s) => OK\n", filename); 707 708 VideoFrame *frame = (VideoFrame *)mem->pointer(); 709 710 SkBitmap bitmap; 711 bitmap.setConfig( 712 SkBitmap::kRGB_565_Config, frame->mWidth, frame->mHeight); 713 714 bitmap.setPixels((uint8_t *)frame + sizeof(VideoFrame)); 715 716 CHECK(SkImageEncoder::EncodeFile( 717 "/sdcard/out.jpg", bitmap, 718 SkImageEncoder::kJPEG_Type, 719 SkImageEncoder::kDefaultQuality)); 720 } 721 722 { 723 mem = retriever->extractAlbumArt(); 724 725 if (mem != NULL) { 726 failed = false; 727 printf("extractAlbumArt(%s) => OK\n", filename); 728 } 729 } 730 731 if (failed) { 732 printf("both getFrameAtTime and extractAlbumArt " 733 "failed on file '%s'.\n", filename); 734 } 735 } 736 737 return 0; 738 } 739 740 if (dumpProfiles) { 741 sp<IServiceManager> sm = defaultServiceManager(); 742 sp<IBinder> binder = sm->getService(String16("media.player")); 743 sp<IMediaPlayerService> service = 744 interface_cast<IMediaPlayerService>(binder); 745 746 CHECK(service.get() != NULL); 747 748 sp<IOMX> omx = service->getOMX(); 749 CHECK(omx.get() != NULL); 750 751 const char *kMimeTypes[] = { 752 MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4, 753 MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AAC, 754 MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB, 755 MEDIA_MIMETYPE_AUDIO_MPEG 756 }; 757 758 for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]); 759 ++k) { 760 printf("type '%s':\n", kMimeTypes[k]); 761 762 Vector<CodecCapabilities> results; 763 CHECK_EQ(QueryCodecs(omx, kMimeTypes[k], 764 true, // queryDecoders 765 &results), (status_t)OK); 766 767 for (size_t i = 0; i < results.size(); ++i) { 768 printf(" decoder '%s' supports ", 769 results[i].mComponentName.string()); 770 771 if (results[i].mProfileLevels.size() == 0) { 772 printf("NOTHING.\n"); 773 continue; 774 } 775 776 for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) { 777 const CodecProfileLevel &profileLevel = 778 results[i].mProfileLevels[j]; 779 780 printf("%s%ld/%ld", j > 0 ? ", " : "", 781 profileLevel.mProfile, profileLevel.mLevel); 782 } 783 784 printf("\n"); 785 } 786 } 787 } 788 789 if (listComponents) { 790 sp<IServiceManager> sm = defaultServiceManager(); 791 sp<IBinder> binder = sm->getService(String16("media.player")); 792 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 793 794 CHECK(service.get() != NULL); 795 796 sp<IOMX> omx = service->getOMX(); 797 CHECK(omx.get() != NULL); 798 799 List<IOMX::ComponentInfo> list; 800 omx->listNodes(&list); 801 802 for (List<IOMX::ComponentInfo>::iterator it = list.begin(); 803 it != list.end(); ++it) { 804 printf("%s\n", (*it).mName.string()); 805 } 806 } 807 808 sp<SurfaceComposerClient> composerClient; 809 sp<SurfaceControl> control; 810 811 if (useSurfaceAlloc && !audioOnly) { 812#if USE_SURFACE_COMPOSER 813 composerClient = new SurfaceComposerClient; 814 CHECK_EQ(composerClient->initCheck(), (status_t)OK); 815 816 control = composerClient->createSurface( 817 getpid(), 818 String8("A Surface"), 819 0, 820 1280, 821 800, 822 PIXEL_FORMAT_RGB_565, 823 0); 824 825 CHECK(control != NULL); 826 CHECK(control->isValid()); 827 828 CHECK_EQ(composerClient->openTransaction(), (status_t)OK); 829 CHECK_EQ(control->setLayer(30000), (status_t)OK); 830 CHECK_EQ(control->show(), (status_t)OK); 831 CHECK_EQ(composerClient->closeTransaction(), (status_t)OK); 832 833 gSurface = control->getSurface(); 834 CHECK(gSurface != NULL); 835#else 836 sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */); 837 gSurface = new SurfaceTextureClient(texture); 838#endif 839 } 840 841 DataSource::RegisterDefaultSniffers(); 842 843 OMXClient client; 844 status_t err = client.connect(); 845 846 for (int k = 0; k < argc; ++k) { 847 bool syncInfoPresent = true; 848 849 const char *filename = argv[k]; 850 851 sp<DataSource> dataSource = DataSource::CreateFromURI(filename); 852 853 if (strncasecmp(filename, "sine:", 5) 854 && strncasecmp(filename, "rtsp://", 7) 855 && strncasecmp(filename, "httplive://", 11) 856 && dataSource == NULL) { 857 fprintf(stderr, "Unable to create data source.\n"); 858 return 1; 859 } 860 861 bool isJPEG = false; 862 863 size_t len = strlen(filename); 864 if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) { 865 isJPEG = true; 866 } 867 868 Vector<sp<MediaSource> > mediaSources; 869 sp<MediaSource> mediaSource; 870 871 if (isJPEG) { 872 mediaSource = new JPEGSource(dataSource); 873 if (gWriteMP4) { 874 mediaSources.push(mediaSource); 875 } 876 } else if (!strncasecmp("sine:", filename, 5)) { 877 char *end; 878 long sampleRate = strtol(filename + 5, &end, 10); 879 880 if (end == filename + 5) { 881 sampleRate = 44100; 882 } 883 mediaSource = new SineSource(sampleRate, 1); 884 if (gWriteMP4) { 885 mediaSources.push(mediaSource); 886 } 887 } else { 888 sp<MediaExtractor> extractor; 889 890 if (!strncasecmp("rtsp://", filename, 7)) { 891 if (looper == NULL) { 892 looper = new ALooper; 893 looper->start(); 894 } 895 896 rtspController = new ARTSPController(looper); 897 status_t err = rtspController->connect(filename); 898 if (err != OK) { 899 fprintf(stderr, "could not connect to rtsp server.\n"); 900 return -1; 901 } 902 903 extractor = rtspController.get(); 904 905 syncInfoPresent = false; 906 } else if (!strncasecmp("httplive://", filename, 11)) { 907 String8 uri("http://"); 908 uri.append(filename + 11); 909 910 if (looper == NULL) { 911 looper = new ALooper; 912 looper->start(); 913 } 914 liveSession = new LiveSession; 915 looper->registerHandler(liveSession); 916 917 liveSession->connect(uri.string()); 918 dataSource = liveSession->getDataSource(); 919 920 extractor = 921 MediaExtractor::Create( 922 dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 923 924 syncInfoPresent = false; 925 } else { 926 extractor = MediaExtractor::Create(dataSource); 927 if (extractor == NULL) { 928 fprintf(stderr, "could not create extractor.\n"); 929 return -1; 930 } 931 } 932 933 size_t numTracks = extractor->countTracks(); 934 935 if (gWriteMP4) { 936 bool haveAudio = false; 937 bool haveVideo = false; 938 for (size_t i = 0; i < numTracks; ++i) { 939 sp<MediaSource> source = extractor->getTrack(i); 940 941 const char *mime; 942 CHECK(source->getFormat()->findCString( 943 kKeyMIMEType, &mime)); 944 945 bool useTrack = false; 946 if (!haveAudio && !strncasecmp("audio/", mime, 6)) { 947 haveAudio = true; 948 useTrack = true; 949 } else if (!haveVideo && !strncasecmp("video/", mime, 6)) { 950 haveVideo = true; 951 useTrack = true; 952 } 953 954 if (useTrack) { 955 mediaSources.push(source); 956 957 if (haveAudio && haveVideo) { 958 break; 959 } 960 } 961 } 962 } else { 963 sp<MetaData> meta; 964 size_t i; 965 for (i = 0; i < numTracks; ++i) { 966 meta = extractor->getTrackMetaData( 967 i, MediaExtractor::kIncludeExtensiveMetaData); 968 969 const char *mime; 970 meta->findCString(kKeyMIMEType, &mime); 971 972 if (audioOnly && !strncasecmp(mime, "audio/", 6)) { 973 break; 974 } 975 976 if (!audioOnly && !strncasecmp(mime, "video/", 6)) { 977 break; 978 } 979 980 meta = NULL; 981 } 982 983 if (meta == NULL) { 984 fprintf(stderr, 985 "No suitable %s track found. The '-a' option will " 986 "target audio tracks only, the default is to target " 987 "video tracks only.\n", 988 audioOnly ? "audio" : "video"); 989 return -1; 990 } 991 992 int64_t thumbTimeUs; 993 if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) { 994 printf("thumbnailTime: %lld us (%.2f secs)\n", 995 thumbTimeUs, thumbTimeUs / 1E6); 996 } 997 998 mediaSource = extractor->getTrack(i); 999 } 1000 } 1001 1002 if (gWriteMP4) { 1003 writeSourcesToMP4(mediaSources, syncInfoPresent); 1004 } else if (seekTest) { 1005 performSeekTest(mediaSource); 1006 } else { 1007 playSource(&client, mediaSource); 1008 } 1009 1010 if (rtspController != NULL) { 1011 rtspController->disconnect(); 1012 rtspController.clear(); 1013 1014 sleep(3); 1015 } 1016 } 1017 1018 if (useSurfaceAlloc && !audioOnly) { 1019 gSurface.clear(); 1020 1021#if USE_SURFACE_COMPOSER 1022 composerClient->dispose(); 1023#endif 1024 } 1025 1026 client.disconnect(); 1027 1028 return 0; 1029} 1030