stagefright.cpp revision 48c948b1137e7bbdb161b51908657ab72ac5e2da
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <sys/time.h> 18 19#include <stdlib.h> 20#include <string.h> 21#include <unistd.h> 22 23#include <binder/IServiceManager.h> 24#include <binder/ProcessState.h> 25#include <media/IMediaPlayerService.h> 26#include <media/stagefright/CachingDataSource.h> 27#include <media/stagefright/HTTPDataSource.h> 28#include <media/stagefright/JPEGSource.h> 29#include <media/stagefright/MediaDebug.h> 30#include <media/stagefright/MediaDefs.h> 31#include <media/stagefright/MediaPlayerImpl.h> 32#include <media/stagefright/MediaExtractor.h> 33#include <media/stagefright/MediaSource.h> 34#include <media/stagefright/MetaData.h> 35#include <media/stagefright/MmapSource.h> 36#include <media/stagefright/OMXClient.h> 37#include <media/stagefright/OMXCodec.h> 38 39using namespace android; 40 41static long gNumRepetitions; 42static long gMaxNumFrames; // 0 means decode all available. 43static long gReproduceBug; // if not -1. 44 45static int64_t getNowUs() { 46 struct timeval tv; 47 gettimeofday(&tv, NULL); 48 49 return (int64_t)tv.tv_usec + tv.tv_sec * 1000000; 50} 51 52static void playSource(OMXClient *client, const sp<MediaSource> &source) { 53 sp<MetaData> meta = source->getFormat(); 54 55 sp<OMXCodec> decoder = OMXCodec::Create( 56 client->interface(), meta, false /* createEncoder */, source); 57 58 if (decoder == NULL) { 59 return; 60 } 61 62 decoder->start(); 63 64 if (gReproduceBug == 3) { 65 status_t err; 66 MediaBuffer *buffer; 67 MediaSource::ReadOptions options; 68 int64_t seekTimeUs = -1; 69 for (;;) { 70 err = decoder->read(&buffer, &options); 71 options.clearSeekTo(); 72 73 bool shouldSeek = false; 74 if (err != OK) { 75 printf("reached EOF.\n"); 76 77 shouldSeek = true; 78 } else { 79 int64_t timestampUs; 80 CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 81 82 bool failed = false; 83 if (seekTimeUs >= 0) { 84 int64_t diff = timestampUs - seekTimeUs; 85 86 if (diff > 500000) { 87 printf("ERROR: "); 88 failed = true; 89 } 90 } 91 92 printf("buffer has timestamp %lld us (%.2f secs)\n", 93 timestampUs, timestampUs / 1E6); 94 95 buffer->release(); 96 buffer = NULL; 97 98 if (failed) { 99 break; 100 } 101 102 shouldSeek = ((double)rand() / RAND_MAX) < 0.1; 103 shouldSeek = false; 104 } 105 106 seekTimeUs = -1; 107 108 if (shouldSeek) { 109 seekTimeUs = (rand() * 30E6) / RAND_MAX; 110 options.setSeekTo(seekTimeUs); 111 112 printf("seeking to %lld us (%.2f secs)\n", 113 seekTimeUs, seekTimeUs / 1E6); 114 } 115 } 116 117 decoder->stop(); 118 119 return; 120 } 121 122 int n = 0; 123 int64_t startTime = getNowUs(); 124 125 long numIterationsLeft = gNumRepetitions; 126 MediaSource::ReadOptions options; 127 128 while (numIterationsLeft-- > 0) { 129 long numFrames = 0; 130 131 MediaBuffer *buffer; 132 133 for (;;) { 134 status_t err = decoder->read(&buffer, &options); 135 options.clearSeekTo(); 136 137 if (err != OK) { 138 CHECK_EQ(buffer, NULL); 139 break; 140 } 141 142 if ((n++ % 16) == 0) { 143 printf("."); 144 fflush(stdout); 145 } 146 147 buffer->release(); 148 buffer = NULL; 149 150 ++numFrames; 151 if (gMaxNumFrames > 0 && numFrames == gMaxNumFrames) { 152 break; 153 } 154 155 if (gReproduceBug == 1 && numFrames == 40) { 156 printf("seeking past the end now."); 157 options.setSeekTo(0x7fffffffL); 158 } else if (gReproduceBug == 2 && numFrames == 40) { 159 printf("seeking to 5 secs."); 160 options.setSeekTo(5000000); 161 } 162 } 163 164 printf("$"); 165 fflush(stdout); 166 167 options.setSeekTo(0); 168 } 169 170 decoder->stop(); 171 printf("\n"); 172 173 int64_t delay = getNowUs() - startTime; 174 printf("avg. %.2f fps\n", n * 1E6 / delay); 175 176 printf("decoded a total of %d frame(s).\n", n); 177} 178 179static void usage(const char *me) { 180 fprintf(stderr, "usage: %s\n", me); 181 fprintf(stderr, " -h(elp)\n"); 182 fprintf(stderr, " -a(udio)\n"); 183 fprintf(stderr, " -n repetitions\n"); 184 fprintf(stderr, " -l(ist) components\n"); 185 fprintf(stderr, " -m max-number-of-frames-to-decode in each pass\n"); 186 fprintf(stderr, " -b bug to reproduce\n"); 187 fprintf(stderr, " -p(rofiles) dump decoder profiles supported\n"); 188} 189 190int main(int argc, char **argv) { 191 android::ProcessState::self()->startThreadPool(); 192 193 bool audioOnly = false; 194 bool listComponents = false; 195 bool dumpProfiles = false; 196 gNumRepetitions = 1; 197 gMaxNumFrames = 0; 198 gReproduceBug = -1; 199 200 int res; 201 while ((res = getopt(argc, argv, "han:lm:b:p")) >= 0) { 202 switch (res) { 203 case 'a': 204 { 205 audioOnly = true; 206 break; 207 } 208 209 case 'l': 210 { 211 listComponents = true; 212 break; 213 } 214 215 case 'm': 216 case 'n': 217 case 'b': 218 { 219 char *end; 220 long x = strtol(optarg, &end, 10); 221 222 if (*end != '\0' || end == optarg || x <= 0) { 223 x = 1; 224 } 225 226 if (res == 'n') { 227 gNumRepetitions = x; 228 } else if (res == 'm') { 229 gMaxNumFrames = x; 230 } else { 231 CHECK_EQ(res, 'b'); 232 gReproduceBug = x; 233 } 234 break; 235 } 236 237 case 'p': 238 { 239 dumpProfiles = true; 240 break; 241 } 242 243 case '?': 244 case 'h': 245 default: 246 { 247 usage(argv[0]); 248 exit(1); 249 break; 250 } 251 } 252 } 253 254 argc -= optind; 255 argv += optind; 256 257 if (dumpProfiles) { 258 sp<IServiceManager> sm = defaultServiceManager(); 259 sp<IBinder> binder = sm->getService(String16("media.player")); 260 sp<IMediaPlayerService> service = 261 interface_cast<IMediaPlayerService>(binder); 262 263 CHECK(service.get() != NULL); 264 265 sp<IOMX> omx = service->createOMX(); 266 CHECK(omx.get() != NULL); 267 268 const char *kMimeTypes[] = { 269 MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4, 270 MEDIA_MIMETYPE_VIDEO_H263 271 }; 272 273 for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]); 274 ++k) { 275 printf("type '%s':\n", kMimeTypes[k]); 276 277 Vector<CodecCapabilities> results; 278 CHECK_EQ(QueryCodecs(omx, kMimeTypes[k], 279 true, // queryDecoders 280 &results), OK); 281 282 for (size_t i = 0; i < results.size(); ++i) { 283 printf(" decoder '%s' supports ", 284 results[i].mComponentName.string()); 285 286 if (results[i].mProfileLevels.size() == 0) { 287 printf("NOTHING.\n"); 288 continue; 289 } 290 291 for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) { 292 const CodecProfileLevel &profileLevel = 293 results[i].mProfileLevels[j]; 294 295 printf("%s%ld/%ld", j > 0 ? ", " : "", 296 profileLevel.mProfile, profileLevel.mLevel); 297 } 298 299 printf("\n"); 300 } 301 } 302 } 303 304 if (listComponents) { 305 sp<IServiceManager> sm = defaultServiceManager(); 306 sp<IBinder> binder = sm->getService(String16("media.player")); 307 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 308 309 CHECK(service.get() != NULL); 310 311 sp<IOMX> omx = service->createOMX(); 312 CHECK(omx.get() != NULL); 313 314 List<String8> list; 315 omx->list_nodes(&list); 316 317 for (List<String8>::iterator it = list.begin(); 318 it != list.end(); ++it) { 319 printf("%s\n", (*it).string()); 320 } 321 } 322 323 DataSource::RegisterDefaultSniffers(); 324 325 OMXClient client; 326 status_t err = client.connect(); 327 328 for (int k = 0; k < argc; ++k) { 329 const char *filename = argv[k]; 330 331 sp<DataSource> dataSource; 332 if (!strncasecmp("http://", filename, 7)) { 333 dataSource = new HTTPDataSource(filename); 334 dataSource = new CachingDataSource(dataSource, 64 * 1024, 10); 335 } else { 336 dataSource = new MmapSource(filename); 337 } 338 339 bool isJPEG = false; 340 341 size_t len = strlen(filename); 342 if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) { 343 isJPEG = true; 344 } 345 346 sp<MediaSource> mediaSource; 347 348 if (isJPEG) { 349 mediaSource = new JPEGSource(dataSource); 350 } else { 351 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 352 353 size_t numTracks = extractor->countTracks(); 354 355 sp<MetaData> meta; 356 size_t i; 357 for (i = 0; i < numTracks; ++i) { 358 meta = extractor->getTrackMetaData(i); 359 360 const char *mime; 361 meta->findCString(kKeyMIMEType, &mime); 362 363 if (audioOnly && !strncasecmp(mime, "audio/", 6)) { 364 break; 365 } 366 367 if (!audioOnly && !strncasecmp(mime, "video/", 6)) { 368 break; 369 } 370 } 371 372 mediaSource = extractor->getTrack(i); 373 } 374 375 playSource(&client, mediaSource); 376 } 377 378 client.disconnect(); 379 380 return 0; 381} 382