stagefright.cpp revision 348a8eab84f4bba76c04ca83b2f5418467aa1a48
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 The Android Open Source Project 353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License"); 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * you may not use this file except in compliance with the License. 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You may obtain a copy of the License at 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * http://www.apache.org/licenses/LICENSE-2.0 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Unless required by applicable law or agreed to in writing, software 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS, 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * See the License for the specific language governing permissions and 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * limitations under the License. 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <sys/time.h> 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <stdlib.h> 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <string.h> 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <unistd.h> 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SineSource.h" 2402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <binder/IServiceManager.h> 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <binder/ProcessState.h> 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/IMediaPlayerService.h> 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/stagefright/foundation/ALooper.h> 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "include/ARTSPController.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/stagefright/AudioPlayer.h> 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <media/stagefright/DataSource.h> 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/stagefright/JPEGSource.h> 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/stagefright/MediaDebug.h> 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/stagefright/MediaDefs.h> 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/stagefright/MediaErrors.h> 3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <media/stagefright/MediaExtractor.h> 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <media/stagefright/MediaSource.h> 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <media/stagefright/MetaData.h> 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/stagefright/OMXClient.h> 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <media/stagefright/OMXCodec.h> 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/mediametadataretriever.h> 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 43591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include <media/stagefright/foundation/hexdump.h> 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <media/stagefright/MPEG4Writer.h> 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace android; 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static long gNumRepetitions; 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static long gMaxNumFrames; // 0 means decode all available. 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static long gReproduceBug; // if not -1. 5193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static bool gPreferSoftwareCodec; 5293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static bool gPlaybackAudio; 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool gWriteMP4; 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static String8 gWriteMP4Filename; 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static int64_t getNowUs() { 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) struct timeval tv; 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gettimeofday(&tv, NULL); 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll; 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void playSource(OMXClient *client, const sp<MediaSource> &source) { 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sp<MetaData> meta = source->getFormat(); 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const char *mime; 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK(meta->findCString(kKeyMIMEType, &mime)); 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sp<MediaSource> rawSource; 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) { 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rawSource = source; 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rawSource = OMXCodec::Create( 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) client->interface(), meta, false /* createEncoder */, source, 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) NULL /* matchComponentName */, 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gPreferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0); 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rawSource == NULL) { 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) status_t err = rawSource->start(); 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (err != OK) { 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, "rawSource returned error %d (0x%08x)\n", err, err); 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (gPlaybackAudio) { 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AudioPlayer *player = new AudioPlayer(NULL); 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) player->setSource(rawSource); 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rawSource.clear(); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) player->start(true /* sourceAlreadyStarted */); 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) status_t finalStatus; 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (!player->reachedEOS(&finalStatus)) { 10002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch usleep(100000ll); 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) delete player; 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) player = NULL; 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (gReproduceBug >= 3 && gReproduceBug <= 5) { 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t durationUs; 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK(meta->findInt64(kKeyDuration, &durationUs)); 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) status_t err; 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MediaBuffer *buffer; 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MediaSource::ReadOptions options; 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t seekTimeUs = -1; 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (;;) { 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) err = rawSource->read(&buffer, &options); 11793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) options.clearSeekTo(); 11893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 11993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) bool shouldSeek = false; 12093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (err == INFO_FORMAT_CHANGED) { 12193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) CHECK_EQ(buffer, NULL); 12293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 12393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) printf("format changed.\n"); 12493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) continue; 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (err != OK) { 12693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) printf("reached EOF.\n"); 12793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 12893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) shouldSeek = true; 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t timestampUs; 13193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 13293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 13393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) bool failed = false; 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (seekTimeUs >= 0) { 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t diff = timestampUs - seekTimeUs; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (diff < 0) { 13953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) diff = -diff; 14053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 14193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 14253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if ((gReproduceBug == 4 && diff > 500000) 14353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) || (gReproduceBug == 5 && timestampUs < 0)) { 14453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) printf("wanted: %.2f secs, got: %.2f secs\n", 14553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) seekTimeUs / 1E6, timestampUs / 1E6); 14653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 14753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) printf("ERROR: "); 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) failed = true; 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("buffer has timestamp %lld us (%.2f secs)\n", 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) timestampUs, timestampUs / 1E6); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer->release(); 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer = NULL; 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (failed) { 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) shouldSeek = ((double)rand() / RAND_MAX) < 0.1; 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (gReproduceBug == 3) { 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) shouldSeek = false; 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) seekTimeUs = -1; 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shouldSeek) { 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) seekTimeUs = (rand() * (float)durationUs) / RAND_MAX; 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options.setSeekTo(seekTimeUs); 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("seeking to %lld us (%.2f secs)\n", 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) seekTimeUs, seekTimeUs / 1E6); 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rawSource->stop(); 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int n = 0; 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t startTime = getNowUs(); 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) long numIterationsLeft = gNumRepetitions; 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MediaSource::ReadOptions options; 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t sumDecodeUs = 0; 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t totalBytes = 0; 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (numIterationsLeft-- > 0) { 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) long numFrames = 0; 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MediaBuffer *buffer; 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (;;) { 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t startDecodeUs = getNowUs(); 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) status_t err = rawSource->read(&buffer, &options); 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t delayDecodeUs = getNowUs() - startDecodeUs; 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options.clearSeekTo(); 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (err != OK) { 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK_EQ(buffer, NULL); 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (err == INFO_FORMAT_CHANGED) { 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("format changed.\n"); 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (buffer->range_length() > 0 && (n++ % 16) == 0) { 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("."); 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fflush(stdout); 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sumDecodeUs += delayDecodeUs; 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totalBytes += buffer->range_length(); 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer->release(); 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer = NULL; 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++numFrames; 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (gMaxNumFrames > 0 && numFrames == gMaxNumFrames) { 23093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) break; 231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 23253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 23353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (gReproduceBug == 1 && numFrames == 40) { 23453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) printf("seeking past the end now."); 23553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) options.setSeekTo(0x7fffffffL); 23653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } else if (gReproduceBug == 2 && numFrames == 40) { 237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) printf("seeking to 5 secs."); 238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) options.setSeekTo(5000000); 239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) printf("$"); 243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) fflush(stdout); 244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) options.setSeekTo(0); 24693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 24793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) rawSource->stop(); 249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) printf("\n"); 250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 25193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) int64_t delay = getNowUs() - startTime; 252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!strncasecmp("video/", mime, 6)) { 253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) printf("avg. %.2f fps\n", n * 1E6 / delay); 254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("avg. time to decode one buffer %.2f usecs\n", 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (double)sumDecodeUs / n); 25793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("decoded a total of %d frame(s).\n", n); 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (!strncasecmp("audio/", mime, 6)) { 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Frame count makes less sense for audio, as the output buffer 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // sizes may be different across decoders. 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("avg. %.2f KB/sec\n", totalBytes / 1024 * 1E6 / delay); 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("decoded a total of %lld bytes\n", totalBytes); 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void writeSourceToMP4(const sp<MediaSource> &source) { 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sp<MPEG4Writer> writer = 27093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) new MPEG4Writer(gWriteMP4Filename.string()); 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK_EQ(writer->addSource(source), OK); 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sp<MetaData> params = new MetaData; 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK_EQ(writer->start(), OK); 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (!writer->reachedEOS()) { 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) usleep(100000); 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 28053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) writer->stop(); 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void performSeekTest(const sp<MediaSource> &source) { 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK_EQ(OK, source->start()); 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int64_t durationUs; 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK(source->getFormat()->findInt64(kKeyDuration, &durationUs)); 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int64_t seekTimeUs = 0; seekTimeUs <= durationUs; 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) seekTimeUs += 60000ll) { 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MediaSource::ReadOptions options; 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options.setSeekTo( 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MediaBuffer *buffer; 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) status_t err; 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (;;) { 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) err = source->read(&buffer, &options); 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) options.clearSeekTo(); 30153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (err == INFO_FORMAT_CHANGED) { 30353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) CHECK(buffer == NULL); 30453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) continue; 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (err != OK) { 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK(buffer == NULL); 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (buffer->range_length() > 0) { 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK(buffer != NULL); 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer->release(); 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer = NULL; 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (err == OK) { 32393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) int64_t timeUs; 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) printf("%lld\t%lld\t%lld\n", seekTimeUs, timeUs, seekTimeUs - timeUs); 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer->release(); 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buffer = NULL; 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 33193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) printf("ERROR\n"); 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK_EQ(OK, source->stop()); 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void usage(const char *me) { 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, "usage: %s\n", me); 34193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fprintf(stderr, " -h(elp)\n"); 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, " -a(udio)\n"); 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, " -n repetitions\n"); 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, " -l(ist) components\n"); 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, " -m max-number-of-frames-to-decode in each pass\n"); 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, " -b bug to reproduce\n"); 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, " -p(rofiles) dump decoder profiles supported\n"); 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, " -t(humbnail) extract video thumbnail or album art\n"); 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, " -s(oftware) prefer software codec\n"); 35053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fprintf(stderr, " -o playback audio\n"); 35153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fprintf(stderr, " -w(rite) filename (write to .mp4 file)\n"); 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fprintf(stderr, " -k seek test\n"); 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int main(int argc, char **argv) { 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) android::ProcessState::self()->startThreadPool(); 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool audioOnly = false; 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool listComponents = false; 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool dumpProfiles = false; 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool extractThumbnail = false; 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool seekTest = false; 36353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) gNumRepetitions = 1; 36453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) gMaxNumFrames = 0; 36553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) gReproduceBug = -1; 36653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) gPreferSoftwareCodec = false; 36753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) gPlaybackAudio = false; 36853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) gWriteMP4 = false; 36953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 37053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) sp<ALooper> looper; 371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sp<ARTSPController> rtspController; 37253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int res; 37453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) while ((res = getopt(argc, argv, "han:lm:b:ptsow:k")) >= 0) { 375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) switch (res) { 376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) case 'a': 377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) { 378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) audioOnly = true; 379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) break; 380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 382 case 'l': 383 { 384 listComponents = true; 385 break; 386 } 387 388 case 'm': 389 case 'n': 390 case 'b': 391 { 392 char *end; 393 long x = strtol(optarg, &end, 10); 394 395 if (*end != '\0' || end == optarg || x <= 0) { 396 x = 1; 397 } 398 399 if (res == 'n') { 400 gNumRepetitions = x; 401 } else if (res == 'm') { 402 gMaxNumFrames = x; 403 } else { 404 CHECK_EQ(res, 'b'); 405 gReproduceBug = x; 406 } 407 break; 408 } 409 410 case 'w': 411 { 412 gWriteMP4 = true; 413 gWriteMP4Filename.setTo(optarg); 414 break; 415 } 416 417 case 'p': 418 { 419 dumpProfiles = true; 420 break; 421 } 422 423 case 't': 424 { 425 extractThumbnail = true; 426 break; 427 } 428 429 case 's': 430 { 431 gPreferSoftwareCodec = true; 432 break; 433 } 434 435 case 'o': 436 { 437 gPlaybackAudio = true; 438 break; 439 } 440 441 case 'k': 442 { 443 seekTest = true; 444 break; 445 } 446 447 case '?': 448 case 'h': 449 default: 450 { 451 usage(argv[0]); 452 exit(1); 453 break; 454 } 455 } 456 } 457 458 if (gPlaybackAudio && !audioOnly) { 459 // This doesn't make any sense if we're decoding the video track. 460 gPlaybackAudio = false; 461 } 462 463 argc -= optind; 464 argv += optind; 465 466 if (extractThumbnail) { 467 sp<IServiceManager> sm = defaultServiceManager(); 468 sp<IBinder> binder = sm->getService(String16("media.player")); 469 sp<IMediaPlayerService> service = 470 interface_cast<IMediaPlayerService>(binder); 471 472 CHECK(service.get() != NULL); 473 474 sp<IMediaMetadataRetriever> retriever = 475 service->createMetadataRetriever(getpid()); 476 477 CHECK(retriever != NULL); 478 479 for (int k = 0; k < argc; ++k) { 480 const char *filename = argv[k]; 481 482 CHECK_EQ(retriever->setDataSource(filename), OK); 483 CHECK_EQ(retriever->setMode( 484 METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL), 485 OK); 486 487 sp<IMemory> mem = retriever->captureFrame(); 488 489 if (mem != NULL) { 490 printf("captureFrame(%s) => OK\n", filename); 491 } else { 492 mem = retriever->extractAlbumArt(); 493 494 if (mem != NULL) { 495 printf("extractAlbumArt(%s) => OK\n", filename); 496 } else { 497 printf("both captureFrame and extractAlbumArt " 498 "failed on file '%s'.\n", filename); 499 } 500 } 501 } 502 503 return 0; 504 } 505 506 if (dumpProfiles) { 507 sp<IServiceManager> sm = defaultServiceManager(); 508 sp<IBinder> binder = sm->getService(String16("media.player")); 509 sp<IMediaPlayerService> service = 510 interface_cast<IMediaPlayerService>(binder); 511 512 CHECK(service.get() != NULL); 513 514 sp<IOMX> omx = service->getOMX(); 515 CHECK(omx.get() != NULL); 516 517 const char *kMimeTypes[] = { 518 MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4, 519 MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AAC, 520 MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB, 521 MEDIA_MIMETYPE_AUDIO_MPEG 522 }; 523 524 for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]); 525 ++k) { 526 printf("type '%s':\n", kMimeTypes[k]); 527 528 Vector<CodecCapabilities> results; 529 CHECK_EQ(QueryCodecs(omx, kMimeTypes[k], 530 true, // queryDecoders 531 &results), OK); 532 533 for (size_t i = 0; i < results.size(); ++i) { 534 printf(" decoder '%s' supports ", 535 results[i].mComponentName.string()); 536 537 if (results[i].mProfileLevels.size() == 0) { 538 printf("NOTHING.\n"); 539 continue; 540 } 541 542 for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) { 543 const CodecProfileLevel &profileLevel = 544 results[i].mProfileLevels[j]; 545 546 printf("%s%ld/%ld", j > 0 ? ", " : "", 547 profileLevel.mProfile, profileLevel.mLevel); 548 } 549 550 printf("\n"); 551 } 552 } 553 } 554 555 if (listComponents) { 556 sp<IServiceManager> sm = defaultServiceManager(); 557 sp<IBinder> binder = sm->getService(String16("media.player")); 558 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 559 560 CHECK(service.get() != NULL); 561 562 sp<IOMX> omx = service->getOMX(); 563 CHECK(omx.get() != NULL); 564 565 List<IOMX::ComponentInfo> list; 566 omx->listNodes(&list); 567 568 for (List<IOMX::ComponentInfo>::iterator it = list.begin(); 569 it != list.end(); ++it) { 570 printf("%s\n", (*it).mName.string()); 571 } 572 } 573 574 DataSource::RegisterDefaultSniffers(); 575 576 OMXClient client; 577 status_t err = client.connect(); 578 579 for (int k = 0; k < argc; ++k) { 580 const char *filename = argv[k]; 581 582 sp<DataSource> dataSource = DataSource::CreateFromURI(filename); 583 584 if ((strncasecmp(filename, "sine:", 5) 585 && strncasecmp(filename, "rtsp://", 7)) && dataSource == NULL) { 586 fprintf(stderr, "Unable to create data source.\n"); 587 return 1; 588 } 589 590 bool isJPEG = false; 591 592 size_t len = strlen(filename); 593 if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) { 594 isJPEG = true; 595 } 596 597 sp<MediaSource> mediaSource; 598 599 if (isJPEG) { 600 mediaSource = new JPEGSource(dataSource); 601 } else if (!strncasecmp("sine:", filename, 5)) { 602 char *end; 603 long sampleRate = strtol(filename + 5, &end, 10); 604 605 if (end == filename + 5) { 606 sampleRate = 44100; 607 } 608 mediaSource = new SineSource(sampleRate, 1); 609 } else { 610 sp<MediaExtractor> extractor; 611 612 if (!strncasecmp("rtsp://", filename, 7)) { 613 if (looper == NULL) { 614 looper = new ALooper; 615 looper->start(); 616 } 617 618 rtspController = new ARTSPController(looper); 619 status_t err = rtspController->connect(filename); 620 if (err != OK) { 621 fprintf(stderr, "could not connect to rtsp server.\n"); 622 return -1; 623 } 624 625 extractor = rtspController.get(); 626 } else { 627 extractor = MediaExtractor::Create(dataSource); 628 if (extractor == NULL) { 629 fprintf(stderr, "could not create extractor.\n"); 630 return -1; 631 } 632 } 633 634 size_t numTracks = extractor->countTracks(); 635 636 sp<MetaData> meta; 637 size_t i; 638 for (i = 0; i < numTracks; ++i) { 639 meta = extractor->getTrackMetaData( 640 i, MediaExtractor::kIncludeExtensiveMetaData); 641 642 const char *mime; 643 meta->findCString(kKeyMIMEType, &mime); 644 645 if (audioOnly && !strncasecmp(mime, "audio/", 6)) { 646 break; 647 } 648 649 if (!audioOnly && !strncasecmp(mime, "video/", 6)) { 650 break; 651 } 652 653 meta = NULL; 654 } 655 656 if (meta == NULL) { 657 fprintf(stderr, 658 "No suitable %s track found. The '-a' option will " 659 "target audio tracks only, the default is to target " 660 "video tracks only.\n", 661 audioOnly ? "audio" : "video"); 662 return -1; 663 } 664 665 int64_t thumbTimeUs; 666 if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) { 667 printf("thumbnailTime: %lld us (%.2f secs)\n", 668 thumbTimeUs, thumbTimeUs / 1E6); 669 } 670 671 mediaSource = extractor->getTrack(i); 672 } 673 674 if (gWriteMP4) { 675 writeSourceToMP4(mediaSource); 676 } else if (seekTest) { 677 performSeekTest(mediaSource); 678 } else { 679 playSource(&client, mediaSource); 680 } 681 682 if (rtspController != NULL) { 683 rtspController->disconnect(); 684 rtspController.clear(); 685 686 sleep(3); 687 } 688 } 689 690 client.disconnect(); 691 692 return 0; 693} 694