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