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