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