stagefright.cpp revision 16afe2fb439cab6125bb46a07a8078d4ce1c1ea5
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber//#define LOG_NDEBUG 0
18bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber#define LOG_TAG "stagefright"
19bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber#include <media/stagefright/foundation/ADebug.h>
20bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <sys/time.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h>
242d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber#include <string.h>
252d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber#include <unistd.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber#include "SineSource.h"
28a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <binder/IServiceManager.h>
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <binder/ProcessState.h>
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/IMediaPlayerService.h>
32348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber#include <media/stagefright/foundation/ALooper.h>
33348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber#include "include/ARTSPController.h"
34ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber#include "include/LiveSource.h"
35ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber#include "include/NuCachedSource2.h"
36a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber#include <media/stagefright/AudioPlayer.h>
371c70247536457f7b7fa84daa3482bd3d3b44e225Andreas Huber#include <media/stagefright/DataSource.h>
38777893a928680f09e306b4b9efc1d5cf4479a9daAndreas Huber#include <media/stagefright/JPEGSource.h>
3918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
401c70247536457f7b7fa84daa3482bd3d3b44e225Andreas Huber#include <media/stagefright/MediaErrors.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaExtractor.h>
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/OMXClient.h>
45693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#include <media/stagefright/OMXCodec.h>
465c1e3581978164d169050686c73810ce59304471Andreas Huber#include <media/mediametadataretriever.h>
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include <media/stagefright/foundation/hexdump.h>
490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include <media/stagefright/MPEG2TSWriter.h>
5019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include <media/stagefright/MPEG4Writer.h>
5119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
52f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber#include <private/media/VideoFrame.h>
53f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber#include <SkBitmap.h>
54f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber#include <SkImageEncoder.h>
55f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
56bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber#include <fcntl.h>
57bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberusing namespace android;
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
602d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huberstatic long gNumRepetitions;
6138b610fe53bb27946826d3f175f6fbe613f270daAndreas Huberstatic long gMaxNumFrames;  // 0 means decode all available.
6280011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huberstatic long gReproduceBug;  // if not -1.
635c1e3581978164d169050686c73810ce59304471Andreas Huberstatic bool gPreferSoftwareCodec;
64a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huberstatic bool gPlaybackAudio;
6519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huberstatic bool gWriteMP4;
66fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huberstatic bool gDisplayHistogram;
6719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huberstatic String8 gWriteMP4Filename;
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic int64_t getNowUs() {
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    struct timeval tv;
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    gettimeofday(&tv, NULL);
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73d2858f047b2c52d719719532f24899c0e03c2099Andreas Huber    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huberstatic int CompareIncreasing(const int64_t *a, const int64_t *b) {
77fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    return (*a) < (*b) ? -1 : (*a) > (*b) ? 1 : 0;
78fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber}
79fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
80fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huberstatic void displayDecodeHistogram(Vector<int64_t> *decodeTimesUs) {
81fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    printf("decode times:\n");
82fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
83fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    decodeTimesUs->sort(CompareIncreasing);
84fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
85fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    size_t n = decodeTimesUs->size();
86fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    int64_t minUs = decodeTimesUs->itemAt(0);
87fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    int64_t maxUs = decodeTimesUs->itemAt(n - 1);
88fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
89fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    printf("min decode time %lld us (%.2f secs)\n", minUs, minUs / 1E6);
90fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    printf("max decode time %lld us (%.2f secs)\n", maxUs, maxUs / 1E6);
91fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
92fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    size_t counts[100];
93fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    for (size_t i = 0; i < 100; ++i) {
94fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        counts[i] = 0;
95fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    }
96fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
97fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    for (size_t i = 0; i < n; ++i) {
98fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        int64_t x = decodeTimesUs->itemAt(i);
99fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
100fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        size_t slot = ((x - minUs) * 100) / (maxUs - minUs);
101fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        if (slot == 100) { slot = 99; }
102fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
103fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        ++counts[slot];
104fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    }
105fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
106fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    for (size_t i = 0; i < 100; ++i) {
107fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        int64_t slotUs = minUs + (i * (maxUs - minUs) / 100);
108fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
109fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        double fps = 1E6 / slotUs;
110fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        printf("[%.2f fps]: %d\n", fps, counts[i]);
111fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    }
112fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber}
113fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
1148a674dcc94936e2306121016ab258b4c00cc9d98James Dongstatic void displayAVCProfileLevelIfPossible(const sp<MetaData>& meta) {
1158a674dcc94936e2306121016ab258b4c00cc9d98James Dong    uint32_t type;
1168a674dcc94936e2306121016ab258b4c00cc9d98James Dong    const void *data;
1178a674dcc94936e2306121016ab258b4c00cc9d98James Dong    size_t size;
1188a674dcc94936e2306121016ab258b4c00cc9d98James Dong    if (meta->findData(kKeyAVCC, &type, &data, &size)) {
1198a674dcc94936e2306121016ab258b4c00cc9d98James Dong        const uint8_t *ptr = (const uint8_t *)data;
1208a674dcc94936e2306121016ab258b4c00cc9d98James Dong        CHECK(size >= 7);
1218a674dcc94936e2306121016ab258b4c00cc9d98James Dong        CHECK(ptr[0] == 1);  // configurationVersion == 1
1228a674dcc94936e2306121016ab258b4c00cc9d98James Dong        uint8_t profile = ptr[1];
1238a674dcc94936e2306121016ab258b4c00cc9d98James Dong        uint8_t level = ptr[3];
1248a674dcc94936e2306121016ab258b4c00cc9d98James Dong        fprintf(stderr, "AVC video profile %d and level %d\n", profile, level);
1258a674dcc94936e2306121016ab258b4c00cc9d98James Dong    }
1268a674dcc94936e2306121016ab258b4c00cc9d98James Dong}
1278a674dcc94936e2306121016ab258b4c00cc9d98James Dong
128c225da975515892952602cd3b1e24efc0cceaa4dAndreas Huberstatic void playSource(OMXClient *client, sp<MediaSource> &source) {
129693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MetaData> meta = source->getFormat();
130693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
131125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber    const char *mime;
132125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber    CHECK(meta->findCString(kKeyMIMEType, &mime));
133125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber
134125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber    sp<MediaSource> rawSource;
135125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
136125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber        rawSource = source;
137125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber    } else {
138125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber        rawSource = OMXCodec::Create(
1395c1e3581978164d169050686c73810ce59304471Andreas Huber            client->interface(), meta, false /* createEncoder */, source,
1405c1e3581978164d169050686c73810ce59304471Andreas Huber            NULL /* matchComponentName */,
1415c1e3581978164d169050686c73810ce59304471Andreas Huber            gPreferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0);
142693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
143125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber        if (rawSource == NULL) {
144125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber            fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime);
145125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber            return;
146125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber        }
1478a674dcc94936e2306121016ab258b4c00cc9d98James Dong        displayAVCProfileLevelIfPossible(meta);
148693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    }
149693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
150c225da975515892952602cd3b1e24efc0cceaa4dAndreas Huber    source.clear();
151c225da975515892952602cd3b1e24efc0cceaa4dAndreas Huber
152139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber    status_t err = rawSource->start();
153139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber
154139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber    if (err != OK) {
155139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber        fprintf(stderr, "rawSource returned error %d (0x%08x)\n", err, err);
156139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber        return;
157139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber    }
158693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
159a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber    if (gPlaybackAudio) {
160a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        AudioPlayer *player = new AudioPlayer(NULL);
161a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        player->setSource(rawSource);
16264105f956f15969dbe1ec7319f6caa2a984e588bAndreas Huber        rawSource.clear();
163a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
164a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        player->start(true /* sourceAlreadyStarted */);
165a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
166a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        status_t finalStatus;
167a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        while (!player->reachedEOS(&finalStatus)) {
168a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            usleep(100000ll);
169a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        }
170a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
171a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        delete player;
172a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        player = NULL;
17364105f956f15969dbe1ec7319f6caa2a984e588bAndreas Huber
17464105f956f15969dbe1ec7319f6caa2a984e588bAndreas Huber        return;
175a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber    } else if (gReproduceBug >= 3 && gReproduceBug <= 5) {
176bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        int64_t durationUs;
177bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        CHECK(meta->findInt64(kKeyDuration, &durationUs));
178bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
1795228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber        status_t err;
1805228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber        MediaBuffer *buffer;
1815228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber        MediaSource::ReadOptions options;
1825228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber        int64_t seekTimeUs = -1;
1835228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber        for (;;) {
184125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber            err = rawSource->read(&buffer, &options);
1855228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber            options.clearSeekTo();
1865228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
1875228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber            bool shouldSeek = false;
1887f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber            if (err == INFO_FORMAT_CHANGED) {
189bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber                CHECK(buffer == NULL);
1907f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber
1917f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber                printf("format changed.\n");
1927f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber                continue;
1937f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber            } else if (err != OK) {
1945228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                printf("reached EOF.\n");
1955228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
1965228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                shouldSeek = true;
1975228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber            } else {
19848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int64_t timestampUs;
19948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
2005228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2015228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                bool failed = false;
202af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber
2035228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                if (seekTimeUs >= 0) {
20448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    int64_t diff = timestampUs - seekTimeUs;
2055228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
206af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                    if (diff < 0) {
207af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                        diff = -diff;
208af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                    }
209af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber
210af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                    if ((gReproduceBug == 4 && diff > 500000)
211af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                        || (gReproduceBug == 5 && timestampUs < 0)) {
212af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                        printf("wanted: %.2f secs, got: %.2f secs\n",
213af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                               seekTimeUs / 1E6, timestampUs / 1E6);
2145228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2155228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                        printf("ERROR: ");
2165228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                        failed = true;
2175228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                    }
2185228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                }
2195228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2205228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                printf("buffer has timestamp %lld us (%.2f secs)\n",
22148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                       timestampUs, timestampUs / 1E6);
2225228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2235228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                buffer->release();
2245228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                buffer = NULL;
2255228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2265228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                if (failed) {
2275228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                    break;
2285228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                }
2295228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2305228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                shouldSeek = ((double)rand() / RAND_MAX) < 0.1;
231af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber
232af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                if (gReproduceBug == 3) {
233af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                    shouldSeek = false;
234af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                }
2355228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber            }
2365228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2375228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber            seekTimeUs = -1;
2385228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2395228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber            if (shouldSeek) {
240af6757c1de099b5352a52b8ed4a67af40f49fc78Andreas Huber                seekTimeUs = (rand() * (float)durationUs) / RAND_MAX;
2415228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                options.setSeekTo(seekTimeUs);
2425228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2435228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                printf("seeking to %lld us (%.2f secs)\n",
2445228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber                       seekTimeUs, seekTimeUs / 1E6);
2455228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber            }
2465228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber        }
2475228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
248125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber        rawSource->stop();
2495228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2505228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber        return;
2515228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber    }
2525228dd1b7468bfc86a807a299f515d33048f96acAndreas Huber
2532d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    int n = 0;
254693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    int64_t startTime = getNowUs();
255693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
2562d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    long numIterationsLeft = gNumRepetitions;
2572d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    MediaSource::ReadOptions options;
258dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
25936e3ee0094e845ed9d2a1c755addecfde9db3a68Andreas Huber    int64_t sumDecodeUs = 0;
2607f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber    int64_t totalBytes = 0;
26136e3ee0094e845ed9d2a1c755addecfde9db3a68Andreas Huber
262fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    Vector<int64_t> decodeTimesUs;
263fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
2642d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    while (numIterationsLeft-- > 0) {
26538b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber        long numFrames = 0;
26638b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber
2672d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        MediaBuffer *buffer;
2682d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
2692d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        for (;;) {
27036e3ee0094e845ed9d2a1c755addecfde9db3a68Andreas Huber            int64_t startDecodeUs = getNowUs();
271125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber            status_t err = rawSource->read(&buffer, &options);
27236e3ee0094e845ed9d2a1c755addecfde9db3a68Andreas Huber            int64_t delayDecodeUs = getNowUs() - startDecodeUs;
27336e3ee0094e845ed9d2a1c755addecfde9db3a68Andreas Huber
2742d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            options.clearSeekTo();
2752d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
2762d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            if (err != OK) {
277bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber                CHECK(buffer == NULL);
2787f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber
2797f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber                if (err == INFO_FORMAT_CHANGED) {
2807f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber                    printf("format changed.\n");
2817f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber                    continue;
2827f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber                }
2837f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber
2842d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                break;
2852d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            }
2862d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
287fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber            if (buffer->range_length() > 0) {
288fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                if (gDisplayHistogram && n > 0) {
289fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                    // Ignore the first time since it includes some setup
290fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                    // cost.
291fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                    decodeTimesUs.push(delayDecodeUs);
292fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                }
293fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
294fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                if ((n++ % 16) == 0) {
295fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                    printf(".");
296fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                    fflush(stdout);
297fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                }
2982d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            }
2992d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
30036e3ee0094e845ed9d2a1c755addecfde9db3a68Andreas Huber            sumDecodeUs += delayDecodeUs;
3017f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber            totalBytes += buffer->range_length();
30236e3ee0094e845ed9d2a1c755addecfde9db3a68Andreas Huber
3032d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            buffer->release();
3042d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            buffer = NULL;
30538b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber
30638b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber            ++numFrames;
30738b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber            if (gMaxNumFrames > 0 && numFrames == gMaxNumFrames) {
30838b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber                break;
30938b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber            }
31080011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber
31180011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber            if (gReproduceBug == 1 && numFrames == 40) {
31280011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber                printf("seeking past the end now.");
313a8a371c8a0d88d144d095404673d00cae6464fdeAndreas Huber                options.setSeekTo(0x7fffffffL);
314e07db23c4935e47ecedfec7537ba95163e5836e5Andreas Huber            } else if (gReproduceBug == 2 && numFrames == 40) {
315e07db23c4935e47ecedfec7537ba95163e5836e5Andreas Huber                printf("seeking to 5 secs.");
316e07db23c4935e47ecedfec7537ba95163e5836e5Andreas Huber                options.setSeekTo(5000000);
31780011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber            }
318693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        }
319693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
3202d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        printf("$");
3212d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        fflush(stdout);
3222d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
3232d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        options.setSeekTo(0);
324693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    }
3252d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
326125ef261deb4efbb50cc41c60902dea48d8d4187Andreas Huber    rawSource->stop();
327693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    printf("\n");
328693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
329693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    int64_t delay = getNowUs() - startTime;
3307f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber    if (!strncasecmp("video/", mime, 6)) {
3317f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber        printf("avg. %.2f fps\n", n * 1E6 / delay);
332693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
3337f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber        printf("avg. time to decode one buffer %.2f usecs\n",
3347f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber               (double)sumDecodeUs / n);
3357f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber
3367f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber        printf("decoded a total of %d frame(s).\n", n);
337fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
338fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        if (gDisplayHistogram) {
339fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber            displayDecodeHistogram(&decodeTimesUs);
340fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber        }
3417f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber    } else if (!strncasecmp("audio/", mime, 6)) {
3427f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber        // Frame count makes less sense for audio, as the output buffer
3437f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber        // sizes may be different across decoders.
3447f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber        printf("avg. %.2f KB/sec\n", totalBytes / 1024 * 1E6 / delay);
3457f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber
3467f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber        printf("decoded a total of %lld bytes\n", totalBytes);
3477f498b90a4300ef9badf14d202b0a67c26e20931Andreas Huber    }
348693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber}
349693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
350bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber////////////////////////////////////////////////////////////////////////////////
351bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
352bbc38312e4521cfd4299203591ef366b7624f043Andreas Huberstruct DetectSyncSource : public MediaSource {
353bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    DetectSyncSource(const sp<MediaSource> &source);
354bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
355bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    virtual status_t start(MetaData *params = NULL);
356bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    virtual status_t stop();
357bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    virtual sp<MetaData> getFormat();
358bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
359bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    virtual status_t read(
360bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber            MediaBuffer **buffer, const ReadOptions *options);
361bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
362bbc38312e4521cfd4299203591ef366b7624f043Andreas Huberprivate:
363ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    enum StreamType {
364ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        AVC,
365ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        MPEG4,
366ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        H263,
367ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        OTHER,
368ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    };
369ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
370bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    sp<MediaSource> mSource;
371ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    StreamType mStreamType;
372bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
373bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource);
374bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber};
375bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
376bbc38312e4521cfd4299203591ef366b7624f043Andreas HuberDetectSyncSource::DetectSyncSource(const sp<MediaSource> &source)
377bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    : mSource(source),
378ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber      mStreamType(OTHER) {
379bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    const char *mime;
380bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
381bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
382ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
383ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        mStreamType = AVC;
384ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
385ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        mStreamType = MPEG4;
386ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        CHECK(!"sync frame detection not implemented yet for MPEG4");
387ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
388ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        mStreamType = H263;
389ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        CHECK(!"sync frame detection not implemented yet for H.263");
390ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    }
391bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber}
392bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
393bbc38312e4521cfd4299203591ef366b7624f043Andreas Huberstatus_t DetectSyncSource::start(MetaData *params) {
394bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    return mSource->start(params);
395bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber}
396bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
397bbc38312e4521cfd4299203591ef366b7624f043Andreas Huberstatus_t DetectSyncSource::stop() {
398bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    return mSource->stop();
399bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber}
400bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
401bbc38312e4521cfd4299203591ef366b7624f043Andreas Hubersp<MetaData> DetectSyncSource::getFormat() {
402bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    return mSource->getFormat();
403bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber}
404bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
405bbc38312e4521cfd4299203591ef366b7624f043Andreas Huberstatic bool isIDRFrame(MediaBuffer *buffer) {
406bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    const uint8_t *data =
407bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
408bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    size_t size = buffer->range_length();
409bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    for (size_t i = 0; i + 3 < size; ++i) {
410bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber        if (!memcmp("\x00\x00\x01", &data[i], 3)) {
411bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber            uint8_t nalType = data[i + 3] & 0x1f;
412bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber            if (nalType == 5) {
413bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber                return true;
414bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber            }
415bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber        }
416bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    }
417bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
418bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    return false;
419bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber}
420bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
421bbc38312e4521cfd4299203591ef366b7624f043Andreas Huberstatus_t DetectSyncSource::read(
422bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
423bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    status_t err = mSource->read(buffer, options);
424bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
425bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    if (err != OK) {
426bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber        return err;
427bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    }
428bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
429ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    if (mStreamType == AVC && isIDRFrame(*buffer)) {
430bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber        (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
431bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    } else {
432ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
433bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    }
434bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
435bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    return OK;
436bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber}
437bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
438bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber////////////////////////////////////////////////////////////////////////////////
439bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
440ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huberstatic void writeSourcesToMP4(
441ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        Vector<sp<MediaSource> > &sources, bool syncInfoPresent) {
4420da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#if 0
44319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    sp<MPEG4Writer> writer =
44419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        new MPEG4Writer(gWriteMP4Filename.string());
4450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#else
4460da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<MPEG2TSWriter> writer =
4470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        new MPEG2TSWriter(gWriteMP4Filename.string());
4480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#endif
44919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
450bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    // at most one minute.
451bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    writer->setMaxFileDuration(60000000ll);
452bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
453ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    for (size_t i = 0; i < sources.size(); ++i) {
454ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        sp<MediaSource> source = sources.editItemAt(i);
455ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
456ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        CHECK_EQ(writer->addSource(
457ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    syncInfoPresent ? source : new DetectSyncSource(source)),
458ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                (status_t)OK);
459ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber    }
46019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
46119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    sp<MetaData> params = new MetaData;
462bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    params->setInt32(kKeyNotRealTime, true);
463bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    CHECK_EQ(writer->start(params.get()), (status_t)OK);
46419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
46519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    while (!writer->reachedEOS()) {
46619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        usleep(100000);
46719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
46819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    writer->stop();
46919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
47019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
47166d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huberstatic void performSeekTest(const sp<MediaSource> &source) {
472bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    CHECK_EQ((status_t)OK, source->start());
47366d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
47466d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber    int64_t durationUs;
47566d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber    CHECK(source->getFormat()->findInt64(kKeyDuration, &durationUs));
47666d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
47766d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber    for (int64_t seekTimeUs = 0; seekTimeUs <= durationUs;
47866d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            seekTimeUs += 60000ll) {
47966d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        MediaSource::ReadOptions options;
48066d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        options.setSeekTo(
48166d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber                seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
48266d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
48366d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        MediaBuffer *buffer;
48466d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        status_t err;
48566d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        for (;;) {
48666d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            err = source->read(&buffer, &options);
48766d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
48866d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            options.clearSeekTo();
48966d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
49066d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            if (err == INFO_FORMAT_CHANGED) {
49166d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber                CHECK(buffer == NULL);
49266d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber                continue;
49366d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            }
49466d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
49566d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            if (err != OK) {
49666d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber                CHECK(buffer == NULL);
49766d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber                break;
49866d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            }
49966d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
50066d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            if (buffer->range_length() > 0) {
50166d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber                break;
50266d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            }
50366d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
50466d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            CHECK(buffer != NULL);
50566d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
50666d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            buffer->release();
50766d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            buffer = NULL;
50866d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        }
50966d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
51066d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        if (err == OK) {
51166d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            int64_t timeUs;
51266d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
51366d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
51466d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            printf("%lld\t%lld\t%lld\n", seekTimeUs, timeUs, seekTimeUs - timeUs);
51566d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
51666d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            buffer->release();
51766d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            buffer = NULL;
51866d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        } else {
51966d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            printf("ERROR\n");
52066d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            break;
52166d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        }
52266d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber    }
52366d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
524bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber    CHECK_EQ((status_t)OK, source->stop());
52566d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber}
52666d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
5272d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huberstatic void usage(const char *me) {
5282d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    fprintf(stderr, "usage: %s\n", me);
5292d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    fprintf(stderr, "       -h(elp)\n");
5302d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    fprintf(stderr, "       -a(udio)\n");
5312d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    fprintf(stderr, "       -n repetitions\n");
5322d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    fprintf(stderr, "       -l(ist) components\n");
53338b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber    fprintf(stderr, "       -m max-number-of-frames-to-decode in each pass\n");
53480011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber    fprintf(stderr, "       -b bug to reproduce\n");
53518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    fprintf(stderr, "       -p(rofiles) dump decoder profiles supported\n");
5361b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber    fprintf(stderr, "       -t(humbnail) extract video thumbnail or album art\n");
5375c1e3581978164d169050686c73810ce59304471Andreas Huber    fprintf(stderr, "       -s(oftware) prefer software codec\n");
538a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber    fprintf(stderr, "       -o playback audio\n");
53919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    fprintf(stderr, "       -w(rite) filename (write to .mp4 file)\n");
54066d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber    fprintf(stderr, "       -k seek test\n");
541fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    fprintf(stderr, "       -x display a histogram of decoding times/fps "
542fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                    "(video only)\n");
5432d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber}
5442d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberint main(int argc, char **argv) {
54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    android::ProcessState::self()->startThreadPool();
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5480024245e134467d120b40099da16c467dc365e76Andreas Huber    bool audioOnly = false;
5492d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    bool listComponents = false;
55018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    bool dumpProfiles = false;
5515c1e3581978164d169050686c73810ce59304471Andreas Huber    bool extractThumbnail = false;
55266d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber    bool seekTest = false;
5532d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    gNumRepetitions = 1;
55438b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber    gMaxNumFrames = 0;
55580011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber    gReproduceBug = -1;
5565c1e3581978164d169050686c73810ce59304471Andreas Huber    gPreferSoftwareCodec = false;
557a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber    gPlaybackAudio = false;
55819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    gWriteMP4 = false;
559fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    gDisplayHistogram = false;
5602d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
561348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber    sp<ALooper> looper;
562348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber    sp<ARTSPController> rtspController;
563348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
5642d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    int res;
565fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber    while ((res = getopt(argc, argv, "han:lm:b:ptsow:kx")) >= 0) {
5662d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        switch (res) {
5672d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            case 'a':
5682d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            {
5692d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                audioOnly = true;
5702d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                break;
5712d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            }
5722d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
5732d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            case 'l':
5742d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            {
5752d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                listComponents = true;
5762d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                break;
5772d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            }
5782d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
57938b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber            case 'm':
5802d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            case 'n':
58180011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber            case 'b':
5822d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            {
5832d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                char *end;
5842d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                long x = strtol(optarg, &end, 10);
5852d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
5862d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                if (*end != '\0' || end == optarg || x <= 0) {
5872d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                    x = 1;
5882d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                }
5892d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
59038b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber                if (res == 'n') {
59138b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber                    gNumRepetitions = x;
59280011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber                } else if (res == 'm') {
59338b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber                    gMaxNumFrames = x;
59480011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber                } else {
59580011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber                    CHECK_EQ(res, 'b');
59680011fe130bc966aa357ed2b3dcc80cde2d0bb82Andreas Huber                    gReproduceBug = x;
59738b610fe53bb27946826d3f175f6fbe613f270daAndreas Huber                }
5982d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                break;
5992d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            }
6002d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
60119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            case 'w':
60219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            {
60319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                gWriteMP4 = true;
60419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                gWriteMP4Filename.setTo(optarg);
60519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                break;
60619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
60719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
60818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            case 'p':
60918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            {
61018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                dumpProfiles = true;
61118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                break;
61218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            }
61318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
6145c1e3581978164d169050686c73810ce59304471Andreas Huber            case 't':
6155c1e3581978164d169050686c73810ce59304471Andreas Huber            {
6165c1e3581978164d169050686c73810ce59304471Andreas Huber                extractThumbnail = true;
6175c1e3581978164d169050686c73810ce59304471Andreas Huber                break;
6185c1e3581978164d169050686c73810ce59304471Andreas Huber            }
6195c1e3581978164d169050686c73810ce59304471Andreas Huber
6205c1e3581978164d169050686c73810ce59304471Andreas Huber            case 's':
6215c1e3581978164d169050686c73810ce59304471Andreas Huber            {
6225c1e3581978164d169050686c73810ce59304471Andreas Huber                gPreferSoftwareCodec = true;
6235c1e3581978164d169050686c73810ce59304471Andreas Huber                break;
6245c1e3581978164d169050686c73810ce59304471Andreas Huber            }
6255c1e3581978164d169050686c73810ce59304471Andreas Huber
626a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            case 'o':
627a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            {
628a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber                gPlaybackAudio = true;
629a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber                break;
630a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            }
631a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
63266d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            case 'k':
63366d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            {
63466d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber                seekTest = true;
63566d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber                break;
63666d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            }
63766d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber
638fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber            case 'x':
639fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber            {
640fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                gDisplayHistogram = true;
641fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber                break;
642fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber            }
643fed975bb3775ebdac136b21e01a9d49aec5b4d23Andreas Huber
6442d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            case '?':
6452d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            case 'h':
6462d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            default:
6472d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            {
6482d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                usage(argv[0]);
6492d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                exit(1);
6502d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                break;
6512d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            }
6522d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        }
6532d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    }
6542d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
655a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber    if (gPlaybackAudio && !audioOnly) {
656a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        // This doesn't make any sense if we're decoding the video track.
657a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        gPlaybackAudio = false;
658a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber    }
659a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
6602d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    argc -= optind;
6612d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    argv += optind;
6622d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
6635c1e3581978164d169050686c73810ce59304471Andreas Huber    if (extractThumbnail) {
6645c1e3581978164d169050686c73810ce59304471Andreas Huber        sp<IServiceManager> sm = defaultServiceManager();
6655c1e3581978164d169050686c73810ce59304471Andreas Huber        sp<IBinder> binder = sm->getService(String16("media.player"));
6665c1e3581978164d169050686c73810ce59304471Andreas Huber        sp<IMediaPlayerService> service =
6675c1e3581978164d169050686c73810ce59304471Andreas Huber            interface_cast<IMediaPlayerService>(binder);
6685c1e3581978164d169050686c73810ce59304471Andreas Huber
6695c1e3581978164d169050686c73810ce59304471Andreas Huber        CHECK(service.get() != NULL);
6705c1e3581978164d169050686c73810ce59304471Andreas Huber
6715c1e3581978164d169050686c73810ce59304471Andreas Huber        sp<IMediaMetadataRetriever> retriever =
6725c1e3581978164d169050686c73810ce59304471Andreas Huber            service->createMetadataRetriever(getpid());
6735c1e3581978164d169050686c73810ce59304471Andreas Huber
6745c1e3581978164d169050686c73810ce59304471Andreas Huber        CHECK(retriever != NULL);
6755c1e3581978164d169050686c73810ce59304471Andreas Huber
6765c1e3581978164d169050686c73810ce59304471Andreas Huber        for (int k = 0; k < argc; ++k) {
6775c1e3581978164d169050686c73810ce59304471Andreas Huber            const char *filename = argv[k];
6785c1e3581978164d169050686c73810ce59304471Andreas Huber
679bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber            CHECK_EQ(retriever->setDataSource(filename), (status_t)OK);
6801b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber            CHECK_EQ(retriever->setMode(
6811b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber                        METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL),
682bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber                     (status_t)OK);
6835c1e3581978164d169050686c73810ce59304471Andreas Huber
68416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong            sp<IMemory> mem =
68516afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong                    retriever->getFrameAtTime(-1,
68616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong                                    MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
6875c1e3581978164d169050686c73810ce59304471Andreas Huber
6881b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber            if (mem != NULL) {
68916afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong                printf("getFrameAtTime(%s) => OK\n", filename);
690f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
691f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                VideoFrame *frame = (VideoFrame *)mem->pointer();
692f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
693f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                SkBitmap bitmap;
694f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                bitmap.setConfig(
695f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                        SkBitmap::kRGB_565_Config, frame->mWidth, frame->mHeight);
696f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
697f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                bitmap.setPixels((uint8_t *)frame + sizeof(VideoFrame));
698f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
699f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                CHECK(SkImageEncoder::EncodeFile(
700f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                            "/sdcard/out.jpg", bitmap,
701f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                            SkImageEncoder::kJPEG_Type,
702f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                            SkImageEncoder::kDefaultQuality));
7031b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber            } else {
7041b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber                mem = retriever->extractAlbumArt();
7051b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber
7061b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber                if (mem != NULL) {
7071b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber                    printf("extractAlbumArt(%s) => OK\n", filename);
7081b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber                } else {
70916afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong                    printf("both getFrameAtTime and extractAlbumArt "
7101b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber                           "failed on file '%s'.\n", filename);
7111b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber                }
7121b950bcd3c11a17186cf971e23f5ec829d092ed5Andreas Huber            }
7135c1e3581978164d169050686c73810ce59304471Andreas Huber        }
7145c1e3581978164d169050686c73810ce59304471Andreas Huber
7155c1e3581978164d169050686c73810ce59304471Andreas Huber        return 0;
7165c1e3581978164d169050686c73810ce59304471Andreas Huber    }
7175c1e3581978164d169050686c73810ce59304471Andreas Huber
71818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    if (dumpProfiles) {
71918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        sp<IServiceManager> sm = defaultServiceManager();
72018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        sp<IBinder> binder = sm->getService(String16("media.player"));
72118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        sp<IMediaPlayerService> service =
72218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            interface_cast<IMediaPlayerService>(binder);
72318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
72418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        CHECK(service.get() != NULL);
72518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
726318ad9c1d9d6515026dfc2c021359d27decaa7a1Andreas Huber        sp<IOMX> omx = service->getOMX();
72718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        CHECK(omx.get() != NULL);
72818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
72918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        const char *kMimeTypes[] = {
73018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
73108a88e195d2b3697f2f967e9216491e8c5bd3c9eAndreas Huber            MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AAC,
73208a88e195d2b3697f2f967e9216491e8c5bd3c9eAndreas Huber            MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB,
73308a88e195d2b3697f2f967e9216491e8c5bd3c9eAndreas Huber            MEDIA_MIMETYPE_AUDIO_MPEG
73418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        };
73518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
73618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]);
73718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber             ++k) {
73818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            printf("type '%s':\n", kMimeTypes[k]);
73918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
74018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            Vector<CodecCapabilities> results;
74118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
74218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                                 true, // queryDecoders
743bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber                                 &results), (status_t)OK);
74418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
74518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            for (size_t i = 0; i < results.size(); ++i) {
74618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                printf("  decoder '%s' supports ",
74718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                       results[i].mComponentName.string());
74818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
74918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                if (results[i].mProfileLevels.size() == 0) {
75018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                    printf("NOTHING.\n");
75118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                    continue;
75218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                }
75318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
75418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
75518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                    const CodecProfileLevel &profileLevel =
75618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                        results[i].mProfileLevels[j];
75718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
75818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                    printf("%s%ld/%ld", j > 0 ? ", " : "",
75918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                           profileLevel.mProfile, profileLevel.mLevel);
76018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                }
76118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
76218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                printf("\n");
76318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            }
76418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        }
76518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    }
76618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber
7672d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    if (listComponents) {
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        sp<IServiceManager> sm = defaultServiceManager();
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        sp<IBinder> binder = sm->getService(String16("media.player"));
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
772693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        CHECK(service.get() != NULL);
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
774318ad9c1d9d6515026dfc2c021359d27decaa7a1Andreas Huber        sp<IOMX> omx = service->getOMX();
775693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        CHECK(omx.get() != NULL);
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
777134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber        List<IOMX::ComponentInfo> list;
778318ad9c1d9d6515026dfc2c021359d27decaa7a1Andreas Huber        omx->listNodes(&list);
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
780134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber        for (List<IOMX::ComponentInfo>::iterator it = list.begin();
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber             it != list.end(); ++it) {
782134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            printf("%s\n", (*it).mName.string());
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    DataSource::RegisterDefaultSniffers();
78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    OMXClient client;
78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err = client.connect();
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7912d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber    for (int k = 0; k < argc; ++k) {
792bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber        bool syncInfoPresent = true;
793bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
7942d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        const char *filename = argv[k];
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7961c70247536457f7b7fa84daa3482bd3d3b44e225Andreas Huber        sp<DataSource> dataSource = DataSource::CreateFromURI(filename);
7970024245e134467d120b40099da16c467dc365e76Andreas Huber
798ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        if (strncasecmp(filename, "sine:", 5)
799ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                && strncasecmp(filename, "rtsp://", 7)
800ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                && strncasecmp(filename, "httplive://", 11)
801ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                && dataSource == NULL) {
802a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            fprintf(stderr, "Unable to create data source.\n");
803a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            return 1;
804a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        }
805a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
8062d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        bool isJPEG = false;
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8082d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        size_t len = strlen(filename);
8092d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) {
8102d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            isJPEG = true;
8112d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        }
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
813ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber        Vector<sp<MediaSource> > mediaSources;
8142d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        sp<MediaSource> mediaSource;
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8162d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        if (isJPEG) {
8172d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            mediaSource = new JPEGSource(dataSource);
818ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber            if (gWriteMP4) {
819ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                mediaSources.push(mediaSource);
820ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber            }
821a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber        } else if (!strncasecmp("sine:", filename, 5)) {
822a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            char *end;
823a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            long sampleRate = strtol(filename + 5, &end, 10);
824a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
825a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            if (end == filename + 5) {
826a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber                sampleRate = 44100;
827a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            }
828a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber            mediaSource = new SineSource(sampleRate, 1);
829ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber            if (gWriteMP4) {
830ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                mediaSources.push(mediaSource);
831ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber            }
8322d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber        } else {
833348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber            sp<MediaExtractor> extractor;
834348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
835348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber            if (!strncasecmp("rtsp://", filename, 7)) {
836348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                if (looper == NULL) {
837348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                    looper = new ALooper;
838348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                    looper->start();
839348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                }
840348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
841348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                rtspController = new ARTSPController(looper);
842348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                status_t err = rtspController->connect(filename);
843348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                if (err != OK) {
844348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                    fprintf(stderr, "could not connect to rtsp server.\n");
845348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                    return -1;
846348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                }
847348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
848348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                extractor = rtspController.get();
849bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber
850bbc38312e4521cfd4299203591ef366b7624f043Andreas Huber                syncInfoPresent = false;
851ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber            } else if (!strncasecmp("httplive://", filename, 11)) {
852ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                String8 uri("http://");
853ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                uri.append(filename + 11);
854ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
855ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                dataSource = new LiveSource(uri.string());
856ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                dataSource = new NuCachedSource2(dataSource);
857ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
858ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                extractor =
859ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    MediaExtractor::Create(
860ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                            dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
861ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
862ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                syncInfoPresent = false;
863348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber            } else {
864348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                extractor = MediaExtractor::Create(dataSource);
865348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                if (extractor == NULL) {
866348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                    fprintf(stderr, "could not create extractor.\n");
867348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                    return -1;
868348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                }
869b93ad64a423975748c7f5e1a5ea94ab8681bc899James Dong            }
87020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8712d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber            size_t numTracks = extractor->countTracks();
87220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
873ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber            if (gWriteMP4) {
874ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                bool haveAudio = false;
875ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                bool haveVideo = false;
876ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                for (size_t i = 0; i < numTracks; ++i) {
877ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    sp<MediaSource> source = extractor->getTrack(i);
878ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
879ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    const char *mime;
880ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    CHECK(source->getFormat()->findCString(
881ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                                kKeyMIMEType, &mime));
882ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
883ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    bool useTrack = false;
884ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    if (!haveAudio && !strncasecmp("audio/", mime, 6)) {
885ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                        haveAudio = true;
886ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                        useTrack = true;
887ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    } else if (!haveVideo && !strncasecmp("video/", mime, 6)) {
888ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                        haveVideo = true;
889ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                        useTrack = true;
890ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    }
89120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
892ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    if (useTrack) {
893ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                        mediaSources.push(source);
89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
895ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                        if (haveAudio && haveVideo) {
896ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                            break;
897ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                        }
898ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    }
8992d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                }
900ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber            } else {
901ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                sp<MetaData> meta;
902ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                size_t i;
903ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                for (i = 0; i < numTracks; ++i) {
904ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    meta = extractor->getTrackMetaData(
905ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                            i, MediaExtractor::kIncludeExtensiveMetaData);
9062d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
907ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    const char *mime;
908ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    meta->findCString(kKeyMIMEType, &mime);
909ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
910ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
911ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                        break;
912ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    }
913ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
914ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
915ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                        break;
916ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    }
917ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber
918ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    meta = NULL;
9192d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber                }
920a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
921ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                if (meta == NULL) {
922ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    fprintf(stderr,
923ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                            "No suitable %s track found. The '-a' option will "
924ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                            "target audio tracks only, the default is to target "
925ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                            "video tracks only.\n",
926ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                            audioOnly ? "audio" : "video");
927ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    return -1;
928ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                }
929a98420e863c374d1f15309467f2a1fc58d979d3bAndreas Huber
930ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                int64_t thumbTimeUs;
931ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) {
932ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                    printf("thumbnailTime: %lld us (%.2f secs)\n",
933ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                           thumbTimeUs, thumbTimeUs / 1E6);
934ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                }
9352d7d46fb2d7f5f80afbf060f25ed049079fb0fc9Andreas Huber
936ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber                mediaSource = extractor->getTrack(i);
9375c1e3581978164d169050686c73810ce59304471Andreas Huber            }
93820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (gWriteMP4) {
941ea314ac049884b31c5a2a4fecc42e8a50f928a33Andreas Huber            writeSourcesToMP4(mediaSources, syncInfoPresent);
94266d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber        } else if (seekTest) {
94366d6f1fcd9cb80a603b833e93779eb0dfb5e67eeAndreas Huber            performSeekTest(mediaSource);
94419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        } else {
94519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            playSource(&client, mediaSource);
94619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
947348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
948348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber        if (rtspController != NULL) {
949348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber            rtspController->disconnect();
950348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber            rtspController.clear();
951348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
952348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber            sleep(3);
953348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber        }
95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    client.disconnect();
95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return 0;
95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
960