1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //#define LOG_NDEBUG 0 18 #define LOG_TAG "sf2" 19 #include <utils/Log.h> 20 21 #include <binder/ProcessState.h> 22 23 #include <media/stagefright/foundation/hexdump.h> 24 #include <media/stagefright/foundation/ABuffer.h> 25 #include <media/stagefright/foundation/ADebug.h> 26 #include <media/stagefright/foundation/ALooper.h> 27 #include <media/stagefright/foundation/AMessage.h> 28 29 #include <media/stagefright/ACodec.h> 30 #include <media/stagefright/DataSource.h> 31 #include <media/stagefright/MediaBuffer.h> 32 #include <media/stagefright/MediaDefs.h> 33 #include <media/stagefright/MediaExtractor.h> 34 #include <media/stagefright/MediaSource.h> 35 #include <media/stagefright/MetaData.h> 36 #include <media/stagefright/NativeWindowWrapper.h> 37 #include <media/stagefright/Utils.h> 38 39 #include <gui/SurfaceComposerClient.h> 40 41 #include "include/ESDS.h" 42 43 using namespace android; 44 45 struct Controller : public AHandler { 46 Controller(const char *uri, bool decodeAudio, 47 const sp<Surface> &surface, bool renderToSurface) 48 : mURI(uri), 49 mDecodeAudio(decodeAudio), 50 mSurface(surface), 51 mRenderToSurface(renderToSurface), 52 mCodec(new ACodec), 53 mIsVorbis(false) { 54 CHECK(!mDecodeAudio || mSurface == NULL); 55 } 56 57 void startAsync() { 58 (new AMessage(kWhatStart, id()))->post(); 59 } 60 61 protected: 62 virtual ~Controller() { 63 } 64 65 virtual void onMessageReceived(const sp<AMessage> &msg) { 66 switch (msg->what()) { 67 case kWhatStart: 68 { 69 #if 1 70 mDecodeLooper = looper(); 71 #else 72 mDecodeLooper = new ALooper; 73 mDecodeLooper->setName("sf2 decode looper"); 74 mDecodeLooper->start(); 75 #endif 76 77 sp<DataSource> dataSource = 78 DataSource::CreateFromURI(mURI.c_str()); 79 80 sp<MediaExtractor> extractor = 81 MediaExtractor::Create(dataSource); 82 83 for (size_t i = 0; i < extractor->countTracks(); ++i) { 84 sp<MetaData> meta = extractor->getTrackMetaData(i); 85 86 const char *mime; 87 CHECK(meta->findCString(kKeyMIMEType, &mime)); 88 89 if (!strncasecmp(mDecodeAudio ? "audio/" : "video/", 90 mime, 6)) { 91 mSource = extractor->getTrack(i); 92 93 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 94 mIsVorbis = true; 95 } else { 96 mIsVorbis = false; 97 } 98 break; 99 } 100 } 101 CHECK(mSource != NULL); 102 103 CHECK_EQ(mSource->start(), (status_t)OK); 104 105 mDecodeLooper->registerHandler(mCodec); 106 107 mCodec->setNotificationMessage( 108 new AMessage(kWhatCodecNotify, id())); 109 110 sp<AMessage> format = makeFormat(mSource->getFormat()); 111 112 if (mSurface != NULL) { 113 format->setObject( 114 "native-window", new NativeWindowWrapper(mSurface)); 115 } 116 117 mCodec->initiateSetup(format); 118 119 mCSDIndex = 0; 120 mStartTimeUs = ALooper::GetNowUs(); 121 mNumOutputBuffersReceived = 0; 122 mTotalBytesReceived = 0; 123 mLeftOverBuffer = NULL; 124 mFinalResult = OK; 125 mSeekState = SEEK_NONE; 126 127 // (new AMessage(kWhatSeek, id()))->post(5000000ll); 128 break; 129 } 130 131 case kWhatSeek: 132 { 133 printf("+"); 134 fflush(stdout); 135 136 CHECK(mSeekState == SEEK_NONE 137 || mSeekState == SEEK_FLUSH_COMPLETED); 138 139 if (mLeftOverBuffer != NULL) { 140 mLeftOverBuffer->release(); 141 mLeftOverBuffer = NULL; 142 } 143 144 mSeekState = SEEK_FLUSHING; 145 mSeekTimeUs = 30000000ll; 146 147 mCodec->signalFlush(); 148 break; 149 } 150 151 case kWhatStop: 152 { 153 if (mLeftOverBuffer != NULL) { 154 mLeftOverBuffer->release(); 155 mLeftOverBuffer = NULL; 156 } 157 158 CHECK_EQ(mSource->stop(), (status_t)OK); 159 mSource.clear(); 160 161 mCodec->initiateShutdown(); 162 break; 163 } 164 165 case kWhatCodecNotify: 166 { 167 int32_t what; 168 CHECK(msg->findInt32("what", &what)); 169 170 if (what == ACodec::kWhatFillThisBuffer) { 171 onFillThisBuffer(msg); 172 } else if (what == ACodec::kWhatDrainThisBuffer) { 173 if ((mNumOutputBuffersReceived++ % 16) == 0) { 174 printf("."); 175 fflush(stdout); 176 } 177 178 onDrainThisBuffer(msg); 179 } else if (what == ACodec::kWhatEOS 180 || what == ACodec::kWhatError) { 181 printf((what == ACodec::kWhatEOS) ? "$\n" : "E\n"); 182 183 int64_t delayUs = ALooper::GetNowUs() - mStartTimeUs; 184 185 if (mDecodeAudio) { 186 printf("%lld bytes received. %.2f KB/sec\n", 187 mTotalBytesReceived, 188 mTotalBytesReceived * 1E6 / 1024 / delayUs); 189 } else { 190 printf("%d frames decoded, %.2f fps. %lld bytes " 191 "received. %.2f KB/sec\n", 192 mNumOutputBuffersReceived, 193 mNumOutputBuffersReceived * 1E6 / delayUs, 194 mTotalBytesReceived, 195 mTotalBytesReceived * 1E6 / 1024 / delayUs); 196 } 197 198 (new AMessage(kWhatStop, id()))->post(); 199 } else if (what == ACodec::kWhatFlushCompleted) { 200 mSeekState = SEEK_FLUSH_COMPLETED; 201 mCodec->signalResume(); 202 203 (new AMessage(kWhatSeek, id()))->post(5000000ll); 204 } else if (what == ACodec::kWhatOutputFormatChanged) { 205 } else if (what == ACodec::kWhatShutdownCompleted) { 206 mDecodeLooper->unregisterHandler(mCodec->id()); 207 208 if (mDecodeLooper != looper()) { 209 mDecodeLooper->stop(); 210 } 211 212 looper()->stop(); 213 } else if (what == ACodec::kWhatError) { 214 ALOGE("something went wrong, codec reported an error."); 215 216 printf("E\n"); 217 218 (new AMessage(kWhatStop, id()))->post(); 219 } 220 break; 221 } 222 223 default: 224 TRESPASS(); 225 break; 226 } 227 } 228 229 private: 230 enum { 231 kWhatStart = 'strt', 232 kWhatStop = 'stop', 233 kWhatCodecNotify = 'noti', 234 kWhatSeek = 'seek', 235 }; 236 237 sp<ALooper> mDecodeLooper; 238 239 AString mURI; 240 bool mDecodeAudio; 241 sp<Surface> mSurface; 242 bool mRenderToSurface; 243 sp<ACodec> mCodec; 244 sp<MediaSource> mSource; 245 bool mIsVorbis; 246 247 Vector<sp<ABuffer> > mCSD; 248 size_t mCSDIndex; 249 250 MediaBuffer *mLeftOverBuffer; 251 status_t mFinalResult; 252 253 int64_t mStartTimeUs; 254 int32_t mNumOutputBuffersReceived; 255 int64_t mTotalBytesReceived; 256 257 enum SeekState { 258 SEEK_NONE, 259 SEEK_FLUSHING, 260 SEEK_FLUSH_COMPLETED, 261 }; 262 SeekState mSeekState; 263 int64_t mSeekTimeUs; 264 265 sp<AMessage> makeFormat(const sp<MetaData> &meta) { 266 CHECK(mCSD.isEmpty()); 267 268 const char *mime; 269 CHECK(meta->findCString(kKeyMIMEType, &mime)); 270 271 sp<AMessage> msg = new AMessage; 272 msg->setString("mime", mime); 273 274 if (!strncasecmp("video/", mime, 6)) { 275 int32_t width, height; 276 CHECK(meta->findInt32(kKeyWidth, &width)); 277 CHECK(meta->findInt32(kKeyHeight, &height)); 278 279 msg->setInt32("width", width); 280 msg->setInt32("height", height); 281 } else { 282 CHECK(!strncasecmp("audio/", mime, 6)); 283 284 int32_t numChannels, sampleRate; 285 CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); 286 CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); 287 288 msg->setInt32("channel-count", numChannels); 289 msg->setInt32("sample-rate", sampleRate); 290 291 int32_t isADTS; 292 if (meta->findInt32(kKeyIsADTS, &isADTS) && isADTS != 0) { 293 msg->setInt32("is-adts", true); 294 } 295 } 296 297 uint32_t type; 298 const void *data; 299 size_t size; 300 if (meta->findData(kKeyAVCC, &type, &data, &size)) { 301 // Parse the AVCDecoderConfigurationRecord 302 303 const uint8_t *ptr = (const uint8_t *)data; 304 305 CHECK(size >= 7); 306 CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 307 uint8_t profile = ptr[1]; 308 uint8_t level = ptr[3]; 309 310 // There is decodable content out there that fails the following 311 // assertion, let's be lenient for now... 312 // CHECK((ptr[4] >> 2) == 0x3f); // reserved 313 314 size_t lengthSize = 1 + (ptr[4] & 3); 315 316 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp 317 // violates it... 318 // CHECK((ptr[5] >> 5) == 7); // reserved 319 320 size_t numSeqParameterSets = ptr[5] & 31; 321 322 ptr += 6; 323 size -= 6; 324 325 sp<ABuffer> buffer = new ABuffer(1024); 326 buffer->setRange(0, 0); 327 328 for (size_t i = 0; i < numSeqParameterSets; ++i) { 329 CHECK(size >= 2); 330 size_t length = U16_AT(ptr); 331 332 ptr += 2; 333 size -= 2; 334 335 CHECK(size >= length); 336 337 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 338 memcpy(buffer->data() + buffer->size() + 4, ptr, length); 339 buffer->setRange(0, buffer->size() + 4 + length); 340 341 ptr += length; 342 size -= length; 343 } 344 345 buffer->meta()->setInt32("csd", true); 346 mCSD.push(buffer); 347 348 buffer = new ABuffer(1024); 349 buffer->setRange(0, 0); 350 351 CHECK(size >= 1); 352 size_t numPictureParameterSets = *ptr; 353 ++ptr; 354 --size; 355 356 for (size_t i = 0; i < numPictureParameterSets; ++i) { 357 CHECK(size >= 2); 358 size_t length = U16_AT(ptr); 359 360 ptr += 2; 361 size -= 2; 362 363 CHECK(size >= length); 364 365 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 366 memcpy(buffer->data() + buffer->size() + 4, ptr, length); 367 buffer->setRange(0, buffer->size() + 4 + length); 368 369 ptr += length; 370 size -= length; 371 } 372 373 buffer->meta()->setInt32("csd", true); 374 mCSD.push(buffer); 375 376 msg->setBuffer("csd", buffer); 377 } else if (meta->findData(kKeyESDS, &type, &data, &size)) { 378 ESDS esds((const char *)data, size); 379 CHECK_EQ(esds.InitCheck(), (status_t)OK); 380 381 const void *codec_specific_data; 382 size_t codec_specific_data_size; 383 esds.getCodecSpecificInfo( 384 &codec_specific_data, &codec_specific_data_size); 385 386 sp<ABuffer> buffer = new ABuffer(codec_specific_data_size); 387 388 memcpy(buffer->data(), codec_specific_data, 389 codec_specific_data_size); 390 391 buffer->meta()->setInt32("csd", true); 392 mCSD.push(buffer); 393 } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) { 394 sp<ABuffer> buffer = new ABuffer(size); 395 memcpy(buffer->data(), data, size); 396 397 buffer->meta()->setInt32("csd", true); 398 mCSD.push(buffer); 399 400 CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size)); 401 402 buffer = new ABuffer(size); 403 memcpy(buffer->data(), data, size); 404 405 buffer->meta()->setInt32("csd", true); 406 mCSD.push(buffer); 407 } 408 409 int32_t maxInputSize; 410 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) { 411 msg->setInt32("max-input-size", maxInputSize); 412 } 413 414 return msg; 415 } 416 417 void onFillThisBuffer(const sp<AMessage> &msg) { 418 sp<AMessage> reply; 419 CHECK(msg->findMessage("reply", &reply)); 420 421 if (mSource == NULL || mSeekState == SEEK_FLUSHING) { 422 reply->setInt32("err", ERROR_END_OF_STREAM); 423 reply->post(); 424 return; 425 } 426 427 sp<ABuffer> outBuffer; 428 CHECK(msg->findBuffer("buffer", &outBuffer)); 429 430 if (mCSDIndex < mCSD.size()) { 431 outBuffer = mCSD.editItemAt(mCSDIndex++); 432 outBuffer->meta()->setInt64("timeUs", 0); 433 } else { 434 size_t sizeLeft = outBuffer->capacity(); 435 outBuffer->setRange(0, 0); 436 437 int32_t n = 0; 438 439 for (;;) { 440 MediaBuffer *inBuffer; 441 442 if (mLeftOverBuffer != NULL) { 443 inBuffer = mLeftOverBuffer; 444 mLeftOverBuffer = NULL; 445 } else if (mFinalResult != OK) { 446 break; 447 } else { 448 MediaSource::ReadOptions options; 449 if (mSeekState == SEEK_FLUSH_COMPLETED) { 450 options.setSeekTo(mSeekTimeUs); 451 mSeekState = SEEK_NONE; 452 } 453 status_t err = mSource->read(&inBuffer, &options); 454 455 if (err != OK) { 456 mFinalResult = err; 457 break; 458 } 459 } 460 461 size_t sizeNeeded = inBuffer->range_length(); 462 if (mIsVorbis) { 463 // Vorbis data is suffixed with the number of 464 // valid samples on the page. 465 sizeNeeded += sizeof(int32_t); 466 } 467 468 if (sizeNeeded > sizeLeft) { 469 if (outBuffer->size() == 0) { 470 ALOGE("Unable to fit even a single input buffer of size %d.", 471 sizeNeeded); 472 } 473 CHECK_GT(outBuffer->size(), 0u); 474 475 mLeftOverBuffer = inBuffer; 476 break; 477 } 478 479 ++n; 480 481 if (outBuffer->size() == 0) { 482 int64_t timeUs; 483 CHECK(inBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 484 485 outBuffer->meta()->setInt64("timeUs", timeUs); 486 } 487 488 memcpy(outBuffer->data() + outBuffer->size(), 489 (const uint8_t *)inBuffer->data() 490 + inBuffer->range_offset(), 491 inBuffer->range_length()); 492 493 if (mIsVorbis) { 494 int32_t numPageSamples; 495 if (!inBuffer->meta_data()->findInt32( 496 kKeyValidSamples, &numPageSamples)) { 497 numPageSamples = -1; 498 } 499 500 memcpy(outBuffer->data() 501 + outBuffer->size() + inBuffer->range_length(), 502 &numPageSamples, sizeof(numPageSamples)); 503 } 504 505 outBuffer->setRange( 506 0, outBuffer->size() + sizeNeeded); 507 508 sizeLeft -= sizeNeeded; 509 510 inBuffer->release(); 511 inBuffer = NULL; 512 513 break; // Don't coalesce 514 } 515 516 ALOGV("coalesced %d input buffers", n); 517 518 if (outBuffer->size() == 0) { 519 CHECK_NE(mFinalResult, (status_t)OK); 520 521 reply->setInt32("err", mFinalResult); 522 reply->post(); 523 return; 524 } 525 } 526 527 reply->setBuffer("buffer", outBuffer); 528 reply->post(); 529 } 530 531 void onDrainThisBuffer(const sp<AMessage> &msg) { 532 sp<ABuffer> buffer; 533 CHECK(msg->findBuffer("buffer", &buffer)); 534 535 mTotalBytesReceived += buffer->size(); 536 537 sp<AMessage> reply; 538 CHECK(msg->findMessage("reply", &reply)); 539 540 if (mRenderToSurface) { 541 reply->setInt32("render", 1); 542 } 543 544 reply->post(); 545 } 546 547 DISALLOW_EVIL_CONSTRUCTORS(Controller); 548 }; 549 550 static void usage(const char *me) { 551 fprintf(stderr, "usage: %s\n", me); 552 fprintf(stderr, " -h(elp)\n"); 553 fprintf(stderr, " -a(udio)\n"); 554 555 fprintf(stderr, 556 " -S(urface) Allocate output buffers on a surface.\n" 557 " -R(ender) Render surface-allocated buffers.\n"); 558 } 559 560 int main(int argc, char **argv) { 561 android::ProcessState::self()->startThreadPool(); 562 563 bool decodeAudio = false; 564 bool useSurface = false; 565 bool renderToSurface = false; 566 567 int res; 568 while ((res = getopt(argc, argv, "haSR")) >= 0) { 569 switch (res) { 570 case 'a': 571 decodeAudio = true; 572 break; 573 574 case 'S': 575 useSurface = true; 576 break; 577 578 case 'R': 579 renderToSurface = true; 580 break; 581 582 case '?': 583 case 'h': 584 default: 585 { 586 usage(argv[0]); 587 return 1; 588 } 589 } 590 } 591 592 argc -= optind; 593 argv += optind; 594 595 if (argc != 1) { 596 usage(argv[-optind]); 597 return 1; 598 } 599 600 DataSource::RegisterDefaultSniffers(); 601 602 sp<ALooper> looper = new ALooper; 603 looper->setName("sf2"); 604 605 sp<SurfaceComposerClient> composerClient; 606 sp<SurfaceControl> control; 607 sp<Surface> surface; 608 609 if (!decodeAudio && useSurface) { 610 composerClient = new SurfaceComposerClient; 611 CHECK_EQ(composerClient->initCheck(), (status_t)OK); 612 613 control = composerClient->createSurface( 614 String8("A Surface"), 615 0, 616 1280, 617 800, 618 PIXEL_FORMAT_RGB_565, 619 0); 620 621 CHECK(control != NULL); 622 CHECK(control->isValid()); 623 624 SurfaceComposerClient::openGlobalTransaction(); 625 CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK); 626 CHECK_EQ(control->show(), (status_t)OK); 627 SurfaceComposerClient::closeGlobalTransaction(); 628 629 surface = control->getSurface(); 630 CHECK(surface != NULL); 631 632 CHECK_EQ((status_t)OK, 633 native_window_api_connect( 634 surface.get(), NATIVE_WINDOW_API_MEDIA)); 635 } 636 637 sp<Controller> controller = 638 new Controller(argv[0], decodeAudio, surface, renderToSurface); 639 640 looper->registerHandler(controller); 641 642 controller->startAsync(); 643 644 CHECK_EQ(looper->start(true /* runOnCallingThread */), (status_t)OK); 645 646 looper->unregisterHandler(controller->id()); 647 648 if (!decodeAudio && useSurface) { 649 CHECK_EQ((status_t)OK, 650 native_window_api_disconnect( 651 surface.get(), NATIVE_WINDOW_API_MEDIA)); 652 653 composerClient->dispose(); 654 } 655 656 return 0; 657 } 658 659