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