sf2.cpp revision f933441648ef6a71dee783d733aac17b9508b452
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 { 174 CHECK_EQ(what, (int32_t)ACodec::kWhatShutdownCompleted); 175 176 mDecodeLooper->unregisterHandler(mCodec->id()); 177 178 if (mDecodeLooper != looper()) { 179 mDecodeLooper->stop(); 180 } 181 182 looper()->stop(); 183 } 184 break; 185 } 186 187 default: 188 TRESPASS(); 189 break; 190 } 191 } 192 193private: 194 enum { 195 kWhatStart = 'strt', 196 kWhatStop = 'stop', 197 kWhatCodecNotify = 'noti', 198 kWhatSeek = 'seek', 199 }; 200 201 sp<ALooper> mDecodeLooper; 202 203 AString mURI; 204 bool mDecodeAudio; 205 sp<Surface> mSurface; 206 sp<ACodec> mCodec; 207 sp<MediaSource> mSource; 208 209 Vector<sp<ABuffer> > mCSD; 210 size_t mCSDIndex; 211 212 MediaBuffer *mLeftOverBuffer; 213 status_t mFinalResult; 214 215 int64_t mStartTimeUs; 216 int32_t mNumOutputBuffersReceived; 217 int64_t mTotalBytesReceived; 218 219 enum SeekState { 220 SEEK_NONE, 221 SEEK_FLUSHING, 222 SEEK_FLUSH_COMPLETED, 223 }; 224 SeekState mSeekState; 225 int64_t mSeekTimeUs; 226 227 sp<AMessage> makeFormat(const sp<MetaData> &meta) { 228 CHECK(mCSD.isEmpty()); 229 230 const char *mime; 231 CHECK(meta->findCString(kKeyMIMEType, &mime)); 232 233 sp<AMessage> msg = new AMessage; 234 msg->setString("mime", mime); 235 236 if (!strncasecmp("video/", mime, 6)) { 237 int32_t width, height; 238 CHECK(meta->findInt32(kKeyWidth, &width)); 239 CHECK(meta->findInt32(kKeyHeight, &height)); 240 241 msg->setInt32("width", width); 242 msg->setInt32("height", height); 243 } else { 244 CHECK(!strncasecmp("audio/", mime, 6)); 245 246 int32_t numChannels, sampleRate; 247 CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); 248 CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); 249 250 msg->setInt32("channel-count", numChannels); 251 msg->setInt32("sample-rate", sampleRate); 252 } 253 254 uint32_t type; 255 const void *data; 256 size_t size; 257 if (meta->findData(kKeyAVCC, &type, &data, &size)) { 258 // Parse the AVCDecoderConfigurationRecord 259 260 const uint8_t *ptr = (const uint8_t *)data; 261 262 CHECK(size >= 7); 263 CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 264 uint8_t profile = ptr[1]; 265 uint8_t level = ptr[3]; 266 267 // There is decodable content out there that fails the following 268 // assertion, let's be lenient for now... 269 // CHECK((ptr[4] >> 2) == 0x3f); // reserved 270 271 size_t lengthSize = 1 + (ptr[4] & 3); 272 273 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp 274 // violates it... 275 // CHECK((ptr[5] >> 5) == 7); // reserved 276 277 size_t numSeqParameterSets = ptr[5] & 31; 278 279 ptr += 6; 280 size -= 6; 281 282 sp<ABuffer> buffer = new ABuffer(1024); 283 buffer->setRange(0, 0); 284 285 for (size_t i = 0; i < numSeqParameterSets; ++i) { 286 CHECK(size >= 2); 287 size_t length = U16_AT(ptr); 288 289 ptr += 2; 290 size -= 2; 291 292 CHECK(size >= length); 293 294 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 295 memcpy(buffer->data() + buffer->size() + 4, ptr, length); 296 buffer->setRange(0, buffer->size() + 4 + length); 297 298 ptr += length; 299 size -= length; 300 } 301 302 buffer->meta()->setInt32("csd", true); 303 mCSD.push(buffer); 304 305 buffer = new ABuffer(1024); 306 buffer->setRange(0, 0); 307 308 CHECK(size >= 1); 309 size_t numPictureParameterSets = *ptr; 310 ++ptr; 311 --size; 312 313 for (size_t i = 0; i < numPictureParameterSets; ++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 msg->setObject("csd", buffer); 334 } else if (meta->findData(kKeyESDS, &type, &data, &size)) { 335 ESDS esds((const char *)data, size); 336 CHECK_EQ(esds.InitCheck(), (status_t)OK); 337 338 const void *codec_specific_data; 339 size_t codec_specific_data_size; 340 esds.getCodecSpecificInfo( 341 &codec_specific_data, &codec_specific_data_size); 342 343 sp<ABuffer> buffer = new ABuffer(codec_specific_data_size); 344 345 memcpy(buffer->data(), codec_specific_data, 346 codec_specific_data_size); 347 348 buffer->meta()->setInt32("csd", true); 349 mCSD.push(buffer); 350 } 351 352 int32_t maxInputSize; 353 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) { 354 msg->setInt32("max-input-size", maxInputSize); 355 } 356 357 return msg; 358 } 359 360 void onFillThisBuffer(const sp<AMessage> &msg) { 361 sp<AMessage> reply; 362 CHECK(msg->findMessage("reply", &reply)); 363 364 if (mSeekState == SEEK_FLUSHING) { 365 reply->post(); 366 return; 367 } 368 369 sp<RefBase> obj; 370 CHECK(msg->findObject("buffer", &obj)); 371 sp<ABuffer> outBuffer = static_cast<ABuffer *>(obj.get()); 372 373 if (mCSDIndex < mCSD.size()) { 374 outBuffer = mCSD.editItemAt(mCSDIndex++); 375 outBuffer->meta()->setInt64("timeUs", 0); 376 } else { 377 size_t sizeLeft = outBuffer->capacity(); 378 outBuffer->setRange(0, 0); 379 380 int32_t n = 0; 381 382 for (;;) { 383 MediaBuffer *inBuffer; 384 385 if (mLeftOverBuffer != NULL) { 386 inBuffer = mLeftOverBuffer; 387 mLeftOverBuffer = NULL; 388 } else if (mFinalResult != OK) { 389 break; 390 } else { 391 MediaSource::ReadOptions options; 392 if (mSeekState == SEEK_FLUSH_COMPLETED) { 393 options.setSeekTo(mSeekTimeUs); 394 mSeekState = SEEK_NONE; 395 } 396 status_t err = mSource->read(&inBuffer, &options); 397 398 if (err != OK) { 399 mFinalResult = err; 400 break; 401 } 402 } 403 404 if (inBuffer->range_length() > sizeLeft) { 405 if (outBuffer->size() == 0) { 406 LOGE("Unable to fit even a single input buffer of size %d.", 407 inBuffer->range_length()); 408 } 409 CHECK_GT(outBuffer->size(), 0u); 410 411 mLeftOverBuffer = inBuffer; 412 break; 413 } 414 415 ++n; 416 417 if (outBuffer->size() == 0) { 418 int64_t timeUs; 419 CHECK(inBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 420 421 outBuffer->meta()->setInt64("timeUs", timeUs); 422 } 423 424 memcpy(outBuffer->data() + outBuffer->size(), 425 (const uint8_t *)inBuffer->data() 426 + inBuffer->range_offset(), 427 inBuffer->range_length()); 428 429 outBuffer->setRange( 430 0, outBuffer->size() + inBuffer->range_length()); 431 432 sizeLeft -= inBuffer->range_length(); 433 434 inBuffer->release(); 435 inBuffer = NULL; 436 437 // break; // Don't coalesce 438 } 439 440 LOGV("coalesced %d input buffers", n); 441 442 if (outBuffer->size() == 0) { 443 CHECK_NE(mFinalResult, (status_t)OK); 444 445 reply->setInt32("err", mFinalResult); 446 reply->post(); 447 return; 448 } 449 } 450 451 reply->setObject("buffer", outBuffer); 452 reply->post(); 453 } 454 455 void onDrainThisBuffer(const sp<AMessage> &msg) { 456 sp<RefBase> obj; 457 CHECK(msg->findObject("buffer", &obj)); 458 459 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 460 mTotalBytesReceived += buffer->size(); 461 462 sp<AMessage> reply; 463 CHECK(msg->findMessage("reply", &reply)); 464 465 reply->post(); 466 } 467 468 DISALLOW_EVIL_CONSTRUCTORS(Controller); 469}; 470 471static void usage(const char *me) { 472 fprintf(stderr, "usage: %s\n", me); 473 fprintf(stderr, " -h(elp)\n"); 474 fprintf(stderr, " -a(udio)\n"); 475 476 fprintf(stderr, 477 " -s(surface) Allocate output buffers on a surface.\n"); 478} 479 480int main(int argc, char **argv) { 481 android::ProcessState::self()->startThreadPool(); 482 483 bool decodeAudio = false; 484 bool useSurface = false; 485 486 int res; 487 while ((res = getopt(argc, argv, "has")) >= 0) { 488 switch (res) { 489 case 'a': 490 decodeAudio = true; 491 break; 492 493 case 's': 494 useSurface = true; 495 break; 496 497 case '?': 498 case 'h': 499 default: 500 { 501 usage(argv[0]); 502 return 1; 503 } 504 } 505 } 506 507 argc -= optind; 508 argv += optind; 509 510 if (argc != 1) { 511 usage(argv[-optind]); 512 return 1; 513 } 514 515 DataSource::RegisterDefaultSniffers(); 516 517 sp<ALooper> looper = new ALooper; 518 looper->setName("sf2"); 519 520 sp<SurfaceComposerClient> composerClient; 521 sp<SurfaceControl> control; 522 sp<Surface> surface; 523 524 if (!decodeAudio && useSurface) { 525 composerClient = new SurfaceComposerClient; 526 CHECK_EQ(composerClient->initCheck(), (status_t)OK); 527 528 control = composerClient->createSurface( 529 getpid(), 530 String8("A Surface"), 531 0, 532 1280, 533 800, 534 PIXEL_FORMAT_RGB_565, 535 0); 536 537 CHECK(control != NULL); 538 CHECK(control->isValid()); 539 540 CHECK_EQ(composerClient->openTransaction(), (status_t)OK); 541 CHECK_EQ(control->setLayer(30000), (status_t)OK); 542 CHECK_EQ(control->show(), (status_t)OK); 543 CHECK_EQ(composerClient->closeTransaction(), (status_t)OK); 544 545 surface = control->getSurface(); 546 CHECK(surface != NULL); 547 } 548 549 sp<Controller> controller = new Controller(argv[0], decodeAudio, surface); 550 looper->registerHandler(controller); 551 552 controller->startAsync(); 553 554 CHECK_EQ(looper->start(true /* runOnCallingThread */), (status_t)OK); 555 556 looper->unregisterHandler(controller->id()); 557 558 if (!decodeAudio && useSurface) { 559 composerClient->dispose(); 560 } 561 562 return 0; 563} 564 565