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