AwesomePlayer.cpp revision 733b7729ea462fae9c6899456444e28fef1c757c
1/* 2 * Copyright (C) 2009 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//#define LOG_NDEBUG 0 18#define LOG_TAG "AwesomePlayer" 19#include <utils/Log.h> 20 21#include "include/AwesomePlayer.h" 22#include "include/SoftwareRenderer.h" 23 24#include <binder/IPCThreadState.h> 25#include <media/stagefright/AudioPlayer.h> 26#include <media/stagefright/DataSource.h> 27#include <media/stagefright/FileSource.h> 28#include <media/stagefright/MediaBuffer.h> 29#include <media/stagefright/MediaExtractor.h> 30#include <media/stagefright/MediaDebug.h> 31#include <media/stagefright/MediaSource.h> 32#include <media/stagefright/MetaData.h> 33#include <media/stagefright/OMXCodec.h> 34namespace android { 35 36struct AwesomeEvent : public TimedEventQueue::Event { 37 AwesomeEvent(AwesomePlayer *player, int32_t code) 38 : mPlayer(player), 39 mCode(code) { 40 } 41 42protected: 43 virtual ~AwesomeEvent() {} 44 45 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 46 mPlayer->onEvent(mCode); 47 } 48 49private: 50 AwesomePlayer *mPlayer; 51 int32_t mCode; 52 53 AwesomeEvent(const AwesomeEvent &); 54 AwesomeEvent &operator=(const AwesomeEvent &); 55}; 56 57struct AwesomeRemoteRenderer : public AwesomeRenderer { 58 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target) 59 : mTarget(target) { 60 } 61 62 virtual void render(MediaBuffer *buffer) { 63 void *id; 64 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { 65 mTarget->render((IOMX::buffer_id)id); 66 } 67 } 68 69private: 70 sp<IOMXRenderer> mTarget; 71 72 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &); 73 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &); 74}; 75 76struct AwesomeLocalRenderer : public AwesomeRenderer { 77 AwesomeLocalRenderer( 78 OMX_COLOR_FORMATTYPE colorFormat, 79 const sp<ISurface> &surface, 80 size_t displayWidth, size_t displayHeight, 81 size_t decodedWidth, size_t decodedHeight) 82 : mTarget(new SoftwareRenderer( 83 colorFormat, surface, displayWidth, displayHeight, 84 decodedWidth, decodedHeight)) { 85 } 86 87 virtual void render(MediaBuffer *buffer) { 88 mTarget->render( 89 (const uint8_t *)buffer->data() + buffer->range_offset(), 90 buffer->range_length(), NULL); 91 } 92 93protected: 94 virtual ~AwesomeLocalRenderer() { 95 delete mTarget; 96 mTarget = NULL; 97 } 98 99private: 100 SoftwareRenderer *mTarget; 101 102 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 103 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 104}; 105 106AwesomePlayer::AwesomePlayer() 107 : mTimeSource(NULL), 108 mAudioPlayer(NULL), 109 mLastVideoBuffer(NULL), 110 mVideoBuffer(NULL) { 111 CHECK_EQ(mClient.connect(), OK); 112 113 DataSource::RegisterDefaultSniffers(); 114 115 mVideoEvent = new AwesomeEvent(this, 0); 116 mVideoEventPending = false; 117 mStreamDoneEvent = new AwesomeEvent(this, 1); 118 mStreamDoneEventPending = false; 119 120 mQueue.start(); 121 122 reset(); 123} 124 125AwesomePlayer::~AwesomePlayer() { 126 mQueue.stop(); 127 128 reset(); 129 130 mClient.disconnect(); 131} 132 133void AwesomePlayer::cancelPlayerEvents() { 134 mQueue.cancelEvent(mVideoEvent->eventID()); 135 mVideoEventPending = false; 136 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 137 mStreamDoneEventPending = false; 138} 139 140void AwesomePlayer::setListener(const sp<MediaPlayerBase> &listener) { 141 Mutex::Autolock autoLock(mLock); 142 mListener = listener; 143} 144 145status_t AwesomePlayer::setDataSource(const char *uri) { 146 Mutex::Autolock autoLock(mLock); 147 148 reset_l(); 149 150 sp<MediaExtractor> extractor = MediaExtractor::CreateFromURI(uri); 151 152 if (extractor == NULL) { 153 return UNKNOWN_ERROR; 154 } 155 156 return setDataSource_l(extractor); 157} 158 159status_t AwesomePlayer::setDataSource( 160 int fd, int64_t offset, int64_t length) { 161 Mutex::Autolock autoLock(mLock); 162 163 reset_l(); 164 165 sp<DataSource> source = new FileSource(fd, offset, length); 166 167 status_t err = source->initCheck(); 168 169 if (err != OK) { 170 return err; 171 } 172 173 sp<MediaExtractor> extractor = MediaExtractor::Create(source); 174 175 if (extractor == NULL) { 176 return UNKNOWN_ERROR; 177 } 178 179 return setDataSource_l(extractor); 180} 181 182status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 183 reset_l(); 184 185 bool haveAudio = false; 186 bool haveVideo = false; 187 for (size_t i = 0; i < extractor->countTracks(); ++i) { 188 sp<MetaData> meta = extractor->getTrackMetaData(i); 189 190 const char *mime; 191 CHECK(meta->findCString(kKeyMIMEType, &mime)); 192 193 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 194 if (setVideoSource(extractor->getTrack(i)) == OK) { 195 haveVideo = true; 196 } 197 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 198 if (setAudioSource(extractor->getTrack(i)) == OK) { 199 haveAudio = true; 200 } 201 } 202 203 if (haveAudio && haveVideo) { 204 break; 205 } 206 } 207 208 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK; 209} 210 211void AwesomePlayer::reset() { 212 Mutex::Autolock autoLock(mLock); 213 reset_l(); 214} 215 216void AwesomePlayer::reset_l() { 217 cancelPlayerEvents(); 218 219 if (mLastVideoBuffer) { 220 mLastVideoBuffer->release(); 221 mLastVideoBuffer = NULL; 222 } 223 224 if (mVideoBuffer) { 225 mVideoBuffer->release(); 226 mVideoBuffer = NULL; 227 } 228 229 if (mVideoSource != NULL) { 230 mVideoSource->stop(); 231 mVideoSource.clear(); 232 } 233 234 mAudioSource.clear(); 235 236 if (mTimeSource != mAudioPlayer) { 237 delete mTimeSource; 238 } 239 mTimeSource = NULL; 240 241 delete mAudioPlayer; 242 mAudioPlayer = NULL; 243 244 mVideoRenderer.clear(); 245 246 mDurationUs = -1; 247 mFlags = 0; 248 mVideoWidth = mVideoHeight = -1; 249 mTimeSourceDeltaUs = 0; 250 mVideoTimeUs = 0; 251 252 mSeeking = false; 253 mSeekTimeUs = 0; 254} 255 256// static 257void AwesomePlayer::AudioNotify(void *_me, int what) { 258 AwesomePlayer *me = (AwesomePlayer *)_me; 259 260 Mutex::Autolock autoLock(me->mLock); 261 262 switch (what) { 263 case AudioPlayer::REACHED_EOS: 264 me->postStreamDoneEvent_l(); 265 break; 266 267 case AudioPlayer::SEEK_COMPLETE: 268 { 269 if (me->mListener != NULL) { 270 me->mListener->sendEvent(MEDIA_SEEK_COMPLETE); 271 } 272 273 break; 274 } 275 276 default: 277 CHECK(!"should not be here."); 278 break; 279 } 280} 281 282void AwesomePlayer::onStreamDone() { 283 // Posted whenever any stream finishes playing. 284 285 Mutex::Autolock autoLock(mLock); 286 mStreamDoneEventPending = false; 287 288 if (mFlags & LOOPING) { 289 seekTo_l(0); 290 291 if (mVideoRenderer != NULL) { 292 postVideoEvent_l(); 293 } 294 } else { 295 if (mListener != NULL) { 296 mListener->sendEvent(MEDIA_PLAYBACK_COMPLETE); 297 } 298 299 pause_l(); 300 } 301} 302 303status_t AwesomePlayer::play() { 304 Mutex::Autolock autoLock(mLock); 305 306 if (mFlags & PLAYING) { 307 return OK; 308 } 309 310 mFlags |= PLAYING; 311 mFlags |= FIRST_FRAME; 312 313 bool deferredAudioSeek = false; 314 315 if (mAudioSource != NULL) { 316 if (mAudioPlayer == NULL) { 317 if (mAudioSink != NULL) { 318 mAudioPlayer = new AudioPlayer(mAudioSink); 319 320 mAudioPlayer->setListenerCallback( 321 &AwesomePlayer::AudioNotify, this); 322 323 mAudioPlayer->setSource(mAudioSource); 324 mAudioPlayer->start(); 325 326 delete mTimeSource; 327 mTimeSource = mAudioPlayer; 328 329 deferredAudioSeek = true; 330 } 331 } else { 332 mAudioPlayer->resume(); 333 } 334 } 335 336 if (mTimeSource == NULL && mAudioPlayer == NULL) { 337 mTimeSource = new SystemTimeSource; 338 } 339 340 if (mVideoSource != NULL) { 341 if (mVideoRenderer == NULL) { 342 initRenderer_l(); 343 } 344 345 if (mVideoRenderer != NULL) { 346 // Kick off video playback 347 postVideoEvent_l(); 348 } 349 } 350 351 if (deferredAudioSeek) { 352 // If there was a seek request while we were paused 353 // and we're just starting up again, honor the request now. 354 seekAudioIfNecessary_l(); 355 } 356 357 return OK; 358} 359 360void AwesomePlayer::initRenderer_l() { 361 if (mISurface != NULL) { 362 sp<MetaData> meta = mVideoSource->getFormat(); 363 364 int32_t format; 365 const char *component; 366 int32_t decodedWidth, decodedHeight; 367 CHECK(meta->findInt32(kKeyColorFormat, &format)); 368 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 369 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 370 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 371 372 mVideoRenderer.clear(); 373 374 // Must ensure that mVideoRenderer's destructor is actually executed 375 // before creating a new one. 376 IPCThreadState::self()->flushCommands(); 377 378 if (!strncmp("OMX.", component, 4)) { 379 // Our OMX codecs allocate buffers on the media_server side 380 // therefore they require a remote IOMXRenderer that knows how 381 // to display them. 382 mVideoRenderer = new AwesomeRemoteRenderer( 383 mClient.interface()->createRenderer( 384 mISurface, component, 385 (OMX_COLOR_FORMATTYPE)format, 386 decodedWidth, decodedHeight, 387 mVideoWidth, mVideoHeight)); 388 } else { 389 // Other decoders are instantiated locally and as a consequence 390 // allocate their buffers in local address space. 391 mVideoRenderer = new AwesomeLocalRenderer( 392 (OMX_COLOR_FORMATTYPE)format, 393 mISurface, 394 mVideoWidth, mVideoHeight, 395 decodedWidth, decodedHeight); 396 } 397 } 398} 399 400status_t AwesomePlayer::pause() { 401 Mutex::Autolock autoLock(mLock); 402 return pause_l(); 403} 404 405status_t AwesomePlayer::pause_l() { 406 if (!(mFlags & PLAYING)) { 407 return OK; 408 } 409 410 cancelPlayerEvents(); 411 412 if (mAudioPlayer != NULL) { 413 mAudioPlayer->pause(); 414 } 415 416 mFlags &= ~PLAYING; 417 418 return OK; 419} 420 421bool AwesomePlayer::isPlaying() const { 422 Mutex::Autolock autoLock(mLock); 423 424 return mFlags & PLAYING; 425} 426 427void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 428 Mutex::Autolock autoLock(mLock); 429 430 mISurface = isurface; 431} 432 433void AwesomePlayer::setAudioSink( 434 const sp<MediaPlayerBase::AudioSink> &audioSink) { 435 Mutex::Autolock autoLock(mLock); 436 437 mAudioSink = audioSink; 438} 439 440status_t AwesomePlayer::setLooping(bool shouldLoop) { 441 Mutex::Autolock autoLock(mLock); 442 443 mFlags = mFlags & ~LOOPING; 444 445 if (shouldLoop) { 446 mFlags |= LOOPING; 447 } 448 449 return OK; 450} 451 452status_t AwesomePlayer::getDuration(int64_t *durationUs) { 453 Mutex::Autolock autoLock(mLock); 454 455 if (mDurationUs < 0) { 456 return UNKNOWN_ERROR; 457 } 458 459 *durationUs = mDurationUs; 460 461 return OK; 462} 463 464status_t AwesomePlayer::getPosition(int64_t *positionUs) { 465 Mutex::Autolock autoLock(mLock); 466 467 if (mVideoRenderer != NULL) { 468 *positionUs = mVideoTimeUs; 469 } else if (mAudioPlayer != NULL) { 470 *positionUs = mAudioPlayer->getMediaTimeUs(); 471 } else { 472 *positionUs = 0; 473 } 474 475 return OK; 476} 477 478status_t AwesomePlayer::seekTo(int64_t timeUs) { 479 Mutex::Autolock autoLock(mLock); 480 return seekTo_l(timeUs); 481} 482 483status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 484 mSeeking = true; 485 mSeekTimeUs = timeUs; 486 487 seekAudioIfNecessary_l(); 488 489 return OK; 490} 491 492void AwesomePlayer::seekAudioIfNecessary_l() { 493 if (mSeeking && mVideoRenderer == NULL && mAudioPlayer != NULL) { 494 mAudioPlayer->seekTo(mSeekTimeUs); 495 496 mSeeking = false; 497 } 498} 499 500status_t AwesomePlayer::getVideoDimensions( 501 int32_t *width, int32_t *height) const { 502 Mutex::Autolock autoLock(mLock); 503 504 if (mVideoWidth < 0 || mVideoHeight < 0) { 505 return UNKNOWN_ERROR; 506 } 507 508 *width = mVideoWidth; 509 *height = mVideoHeight; 510 511 return OK; 512} 513 514status_t AwesomePlayer::setAudioSource(const sp<MediaSource> &source) { 515 if (source == NULL) { 516 return UNKNOWN_ERROR; 517 } 518 519 mAudioSource = OMXCodec::Create( 520 mClient.interface(), source->getFormat(), 521 false, // createEncoder 522 source); 523 524 if (mAudioSource != NULL) { 525 int64_t durationUs; 526 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) { 527 if (mDurationUs < 0 || durationUs > mDurationUs) { 528 mDurationUs = durationUs; 529 } 530 } 531 } 532 533 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 534} 535 536status_t AwesomePlayer::setVideoSource(const sp<MediaSource> &source) { 537 if (source == NULL) { 538 return UNKNOWN_ERROR; 539 } 540 541 mVideoSource = OMXCodec::Create( 542 mClient.interface(), source->getFormat(), 543 false, // createEncoder 544 source); 545 546 if (mVideoSource != NULL) { 547 int64_t durationUs; 548 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) { 549 if (mDurationUs < 0 || durationUs > mDurationUs) { 550 mDurationUs = durationUs; 551 } 552 } 553 554 CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 555 CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 556 557 mVideoSource->start(); 558 } 559 560 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 561} 562 563void AwesomePlayer::onEvent(int32_t code) { 564 if (code == 1) { 565 onStreamDone(); 566 return; 567 } 568 569 Mutex::Autolock autoLock(mLock); 570 mVideoEventPending = false; 571 572 if (mSeeking) { 573 if (mLastVideoBuffer) { 574 mLastVideoBuffer->release(); 575 mLastVideoBuffer = NULL; 576 } 577 578 if (mVideoBuffer) { 579 mVideoBuffer->release(); 580 mVideoBuffer = NULL; 581 } 582 } 583 584 if (!mVideoBuffer) { 585 MediaSource::ReadOptions options; 586 if (mSeeking) { 587 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 588 589 options.setSeekTo(mSeekTimeUs); 590 } 591 for (;;) { 592 status_t err = mVideoSource->read(&mVideoBuffer, &options); 593 594 if (err != OK) { 595 CHECK_EQ(mVideoBuffer, NULL); 596 597 if (err == INFO_FORMAT_CHANGED) { 598 LOGV("VideoSource signalled format change."); 599 600 initRenderer_l(); 601 continue; 602 } 603 604 postStreamDoneEvent_l(); 605 return; 606 } 607 608 if (mVideoBuffer->range_length() == 0) { 609 // Some decoders, notably the PV AVC software decoder 610 // return spurious empty buffers that we just want to ignore. 611 612 mVideoBuffer->release(); 613 mVideoBuffer = NULL; 614 continue; 615 } 616 617 break; 618 } 619 } 620 621 int64_t timeUs; 622 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 623 624 mVideoTimeUs = timeUs; 625 626 if (mSeeking) { 627 if (mAudioPlayer != NULL) { 628 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6); 629 630 mAudioPlayer->seekTo(timeUs); 631 } else { 632 // If we're playing video only, report seek complete now, 633 // otherwise audio player will notify us later. 634 if (mListener != NULL) { 635 mListener->sendEvent(MEDIA_SEEK_COMPLETE); 636 } 637 } 638 639 mFlags |= FIRST_FRAME; 640 mSeeking = false; 641 } 642 643 if (mFlags & FIRST_FRAME) { 644 mFlags &= ~FIRST_FRAME; 645 646 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs; 647 } 648 649 int64_t realTimeUs, mediaTimeUs; 650 if (mAudioPlayer != NULL 651 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 652 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 653 } 654 655 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs; 656 657 int64_t latenessUs = nowUs - timeUs; 658 659 if (latenessUs > 40000) { 660 // We're more than 40ms late. 661 LOGI("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 662 663 mVideoBuffer->release(); 664 mVideoBuffer = NULL; 665 666 postVideoEvent_l(); 667 return; 668 } 669 670 if (latenessUs < -10000) { 671 // We're more than 10ms early. 672 673 postVideoEvent_l(10000); 674 return; 675 } 676 677 mVideoRenderer->render(mVideoBuffer); 678 679 if (mLastVideoBuffer) { 680 mLastVideoBuffer->release(); 681 mLastVideoBuffer = NULL; 682 } 683 mLastVideoBuffer = mVideoBuffer; 684 mVideoBuffer = NULL; 685 686 postVideoEvent_l(); 687} 688 689void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 690 if (mVideoEventPending) { 691 return; 692 } 693 694 mVideoEventPending = true; 695 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 696} 697 698void AwesomePlayer::postStreamDoneEvent_l() { 699 if (mStreamDoneEventPending) { 700 return; 701 } 702 mStreamDoneEventPending = true; 703 mQueue.postEvent(mStreamDoneEvent); 704} 705 706} // namespace android 707 708