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