NuPlayerDriver.cpp revision 62cc8d0d9d8019a84e6ef63c3917d3beb99061c6
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//#define LOG_NDEBUG 0 18#define LOG_TAG "NuPlayerDriver" 19#include <inttypes.h> 20#include <utils/Log.h> 21#include <cutils/properties.h> 22 23#include "NuPlayerDriver.h" 24 25#include "NuPlayer.h" 26#include "NuPlayerSource.h" 27 28#include <media/stagefright/foundation/ADebug.h> 29#include <media/stagefright/foundation/ALooper.h> 30#include <media/stagefright/foundation/AUtils.h> 31#include <media/stagefright/MetaData.h> 32#include <media/stagefright/Utils.h> 33 34namespace android { 35 36NuPlayerDriver::NuPlayerDriver(pid_t pid) 37 : mState(STATE_IDLE), 38 mIsAsyncPrepare(false), 39 mAsyncResult(UNKNOWN_ERROR), 40 mSetSurfaceInProgress(false), 41 mDurationUs(-1), 42 mPositionUs(-1), 43 mSeekInProgress(false), 44 mLooper(new ALooper), 45 mPlayerFlags(0), 46 mAtEOS(false), 47 mLooping(false), 48 mAutoLoop(false), 49 mStartupSeekTimeUs(-1) { 50 ALOGV("NuPlayerDriver(%p)", this); 51 mLooper->setName("NuPlayerDriver Looper"); 52 53 mLooper->start( 54 false, /* runOnCallingThread */ 55 true, /* canCallJava */ 56 PRIORITY_AUDIO); 57 58 mPlayer = new NuPlayer(pid); 59 mLooper->registerHandler(mPlayer); 60 61 mPlayer->setDriver(this); 62} 63 64NuPlayerDriver::~NuPlayerDriver() { 65 ALOGV("~NuPlayerDriver(%p)", this); 66 mLooper->stop(); 67} 68 69status_t NuPlayerDriver::initCheck() { 70 return OK; 71} 72 73status_t NuPlayerDriver::setUID(uid_t uid) { 74 mPlayer->setUID(uid); 75 76 return OK; 77} 78 79status_t NuPlayerDriver::setDataSource( 80 const sp<IMediaHTTPService> &httpService, 81 const char *url, 82 const KeyedVector<String8, String8> *headers) { 83 ALOGV("setDataSource(%p) url(%s)", this, uriDebugString(url, false).c_str()); 84 Mutex::Autolock autoLock(mLock); 85 86 if (mState != STATE_IDLE) { 87 return INVALID_OPERATION; 88 } 89 90 mState = STATE_SET_DATASOURCE_PENDING; 91 92 mPlayer->setDataSourceAsync(httpService, url, headers); 93 94 while (mState == STATE_SET_DATASOURCE_PENDING) { 95 mCondition.wait(mLock); 96 } 97 98 return mAsyncResult; 99} 100 101status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) { 102 ALOGV("setDataSource(%p) file(%d)", this, fd); 103 Mutex::Autolock autoLock(mLock); 104 105 if (mState != STATE_IDLE) { 106 return INVALID_OPERATION; 107 } 108 109 mState = STATE_SET_DATASOURCE_PENDING; 110 111 mPlayer->setDataSourceAsync(fd, offset, length); 112 113 while (mState == STATE_SET_DATASOURCE_PENDING) { 114 mCondition.wait(mLock); 115 } 116 117 return mAsyncResult; 118} 119 120status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) { 121 ALOGV("setDataSource(%p) stream source", this); 122 Mutex::Autolock autoLock(mLock); 123 124 if (mState != STATE_IDLE) { 125 return INVALID_OPERATION; 126 } 127 128 mState = STATE_SET_DATASOURCE_PENDING; 129 130 mPlayer->setDataSourceAsync(source); 131 132 while (mState == STATE_SET_DATASOURCE_PENDING) { 133 mCondition.wait(mLock); 134 } 135 136 return mAsyncResult; 137} 138 139status_t NuPlayerDriver::setDataSource(const sp<DataSource> &source) { 140 ALOGV("setDataSource(%p) callback source", this); 141 Mutex::Autolock autoLock(mLock); 142 143 if (mState != STATE_IDLE) { 144 return INVALID_OPERATION; 145 } 146 147 mState = STATE_SET_DATASOURCE_PENDING; 148 149 mPlayer->setDataSourceAsync(source); 150 151 while (mState == STATE_SET_DATASOURCE_PENDING) { 152 mCondition.wait(mLock); 153 } 154 155 return mAsyncResult; 156} 157 158status_t NuPlayerDriver::setVideoSurfaceTexture( 159 const sp<IGraphicBufferProducer> &bufferProducer) { 160 ALOGV("setVideoSurfaceTexture(%p)", this); 161 Mutex::Autolock autoLock(mLock); 162 163 if (mSetSurfaceInProgress) { 164 return INVALID_OPERATION; 165 } 166 167 switch (mState) { 168 case STATE_SET_DATASOURCE_PENDING: 169 case STATE_RESET_IN_PROGRESS: 170 return INVALID_OPERATION; 171 172 default: 173 break; 174 } 175 176 mSetSurfaceInProgress = true; 177 178 mPlayer->setVideoSurfaceTextureAsync(bufferProducer); 179 180 while (mSetSurfaceInProgress) { 181 mCondition.wait(mLock); 182 } 183 184 return OK; 185} 186 187status_t NuPlayerDriver::prepare() { 188 ALOGV("prepare(%p)", this); 189 Mutex::Autolock autoLock(mLock); 190 return prepare_l(); 191} 192 193status_t NuPlayerDriver::prepare_l() { 194 switch (mState) { 195 case STATE_UNPREPARED: 196 mState = STATE_PREPARING; 197 198 // Make sure we're not posting any notifications, success or 199 // failure information is only communicated through our result 200 // code. 201 mIsAsyncPrepare = false; 202 mPlayer->prepareAsync(); 203 while (mState == STATE_PREPARING) { 204 mCondition.wait(mLock); 205 } 206 return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR; 207 case STATE_STOPPED: 208 // this is really just paused. handle as seek to start 209 mAtEOS = false; 210 mState = STATE_STOPPED_AND_PREPARING; 211 mIsAsyncPrepare = false; 212 mPlayer->seekToAsync(0, true /* needNotify */); 213 while (mState == STATE_STOPPED_AND_PREPARING) { 214 mCondition.wait(mLock); 215 } 216 return (mState == STATE_STOPPED_AND_PREPARED) ? OK : UNKNOWN_ERROR; 217 default: 218 return INVALID_OPERATION; 219 }; 220} 221 222status_t NuPlayerDriver::prepareAsync() { 223 ALOGV("prepareAsync(%p)", this); 224 Mutex::Autolock autoLock(mLock); 225 226 switch (mState) { 227 case STATE_UNPREPARED: 228 mState = STATE_PREPARING; 229 mIsAsyncPrepare = true; 230 mPlayer->prepareAsync(); 231 return OK; 232 case STATE_STOPPED: 233 // this is really just paused. handle as seek to start 234 mAtEOS = false; 235 mState = STATE_STOPPED_AND_PREPARING; 236 mIsAsyncPrepare = true; 237 mPlayer->seekToAsync(0, true /* needNotify */); 238 return OK; 239 default: 240 return INVALID_OPERATION; 241 }; 242} 243 244status_t NuPlayerDriver::start() { 245 ALOGD("start(%p), state is %d, eos is %d", this, mState, mAtEOS); 246 Mutex::Autolock autoLock(mLock); 247 248 switch (mState) { 249 case STATE_UNPREPARED: 250 { 251 status_t err = prepare_l(); 252 253 if (err != OK) { 254 return err; 255 } 256 257 CHECK_EQ(mState, STATE_PREPARED); 258 259 // fall through 260 } 261 262 case STATE_PAUSED: 263 case STATE_STOPPED_AND_PREPARED: 264 { 265 if (mAtEOS && mStartupSeekTimeUs < 0) { 266 mStartupSeekTimeUs = 0; 267 mPositionUs = -1; 268 } 269 270 // fall through 271 } 272 273 case STATE_PREPARED: 274 { 275 mAtEOS = false; 276 mPlayer->start(); 277 278 if (mStartupSeekTimeUs >= 0) { 279 mPlayer->seekToAsync(mStartupSeekTimeUs); 280 mStartupSeekTimeUs = -1; 281 } 282 break; 283 } 284 285 case STATE_RUNNING: 286 { 287 if (mAtEOS) { 288 mPlayer->seekToAsync(0); 289 mAtEOS = false; 290 mPositionUs = -1; 291 } 292 break; 293 } 294 295 default: 296 return INVALID_OPERATION; 297 } 298 299 mState = STATE_RUNNING; 300 301 return OK; 302} 303 304status_t NuPlayerDriver::stop() { 305 ALOGD("stop(%p)", this); 306 Mutex::Autolock autoLock(mLock); 307 308 switch (mState) { 309 case STATE_RUNNING: 310 mPlayer->pause(); 311 // fall through 312 313 case STATE_PAUSED: 314 mState = STATE_STOPPED; 315 notifyListener_l(MEDIA_STOPPED); 316 break; 317 318 case STATE_PREPARED: 319 case STATE_STOPPED: 320 case STATE_STOPPED_AND_PREPARING: 321 case STATE_STOPPED_AND_PREPARED: 322 mState = STATE_STOPPED; 323 break; 324 325 default: 326 return INVALID_OPERATION; 327 } 328 329 return OK; 330} 331 332status_t NuPlayerDriver::pause() { 333 // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear 334 // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the 335 // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling 336 // getCurrentPosition here. 337 int unused; 338 getCurrentPosition(&unused); 339 340 Mutex::Autolock autoLock(mLock); 341 342 switch (mState) { 343 case STATE_PAUSED: 344 case STATE_PREPARED: 345 return OK; 346 347 case STATE_RUNNING: 348 mState = STATE_PAUSED; 349 notifyListener_l(MEDIA_PAUSED); 350 mPlayer->pause(); 351 break; 352 353 default: 354 return INVALID_OPERATION; 355 } 356 357 return OK; 358} 359 360bool NuPlayerDriver::isPlaying() { 361 return mState == STATE_RUNNING && !mAtEOS; 362} 363 364status_t NuPlayerDriver::setPlaybackSettings(const AudioPlaybackRate &rate) { 365 status_t err = mPlayer->setPlaybackSettings(rate); 366 if (err == OK) { 367 // try to update position 368 int unused; 369 getCurrentPosition(&unused); 370 Mutex::Autolock autoLock(mLock); 371 if (rate.mSpeed == 0.f && mState == STATE_RUNNING) { 372 mState = STATE_PAUSED; 373 notifyListener_l(MEDIA_PAUSED); 374 } else if (rate.mSpeed != 0.f && mState == STATE_PAUSED) { 375 mState = STATE_RUNNING; 376 } 377 } 378 return err; 379} 380 381status_t NuPlayerDriver::getPlaybackSettings(AudioPlaybackRate *rate) { 382 return mPlayer->getPlaybackSettings(rate); 383} 384 385status_t NuPlayerDriver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) { 386 return mPlayer->setSyncSettings(sync, videoFpsHint); 387} 388 389status_t NuPlayerDriver::getSyncSettings(AVSyncSettings *sync, float *videoFps) { 390 return mPlayer->getSyncSettings(sync, videoFps); 391} 392 393status_t NuPlayerDriver::seekTo(int msec) { 394 ALOGD("seekTo(%p) %d ms at state %d", this, msec, mState); 395 Mutex::Autolock autoLock(mLock); 396 397 int64_t seekTimeUs = msec * 1000ll; 398 399 switch (mState) { 400 case STATE_PREPARED: 401 case STATE_STOPPED_AND_PREPARED: 402 case STATE_PAUSED: 403 mStartupSeekTimeUs = seekTimeUs; 404 // fall through. 405 case STATE_RUNNING: 406 { 407 mAtEOS = false; 408 mSeekInProgress = true; 409 // seeks can take a while, so we essentially paused 410 notifyListener_l(MEDIA_PAUSED); 411 mPlayer->seekToAsync(seekTimeUs, true /* needNotify */); 412 break; 413 } 414 415 default: 416 return INVALID_OPERATION; 417 } 418 419 mPositionUs = seekTimeUs; 420 return OK; 421} 422 423status_t NuPlayerDriver::getCurrentPosition(int *msec) { 424 int64_t tempUs = 0; 425 { 426 Mutex::Autolock autoLock(mLock); 427 if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) { 428 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs; 429 *msec = (int)divRound(tempUs, (int64_t)(1000)); 430 return OK; 431 } 432 } 433 434 status_t ret = mPlayer->getCurrentPosition(&tempUs); 435 436 Mutex::Autolock autoLock(mLock); 437 // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which 438 // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a 439 // position value that's different the seek to position. 440 if (ret != OK) { 441 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs; 442 } else { 443 mPositionUs = tempUs; 444 } 445 *msec = (int)divRound(tempUs, (int64_t)(1000)); 446 return OK; 447} 448 449status_t NuPlayerDriver::getDuration(int *msec) { 450 Mutex::Autolock autoLock(mLock); 451 452 if (mDurationUs < 0) { 453 return UNKNOWN_ERROR; 454 } 455 456 *msec = (mDurationUs + 500ll) / 1000; 457 458 return OK; 459} 460 461status_t NuPlayerDriver::reset() { 462 ALOGD("reset(%p) at state %d", this, mState); 463 Mutex::Autolock autoLock(mLock); 464 465 switch (mState) { 466 case STATE_IDLE: 467 return OK; 468 469 case STATE_SET_DATASOURCE_PENDING: 470 case STATE_RESET_IN_PROGRESS: 471 return INVALID_OPERATION; 472 473 case STATE_PREPARING: 474 { 475 CHECK(mIsAsyncPrepare); 476 477 notifyListener_l(MEDIA_PREPARED); 478 break; 479 } 480 481 default: 482 break; 483 } 484 485 if (mState != STATE_STOPPED) { 486 notifyListener_l(MEDIA_STOPPED); 487 } 488 489 char value[PROPERTY_VALUE_MAX]; 490 if (property_get("persist.debug.sf.stats", value, NULL) && 491 (!strcmp("1", value) || !strcasecmp("true", value))) { 492 Vector<String16> args; 493 dump(-1, args); 494 } 495 496 mState = STATE_RESET_IN_PROGRESS; 497 mPlayer->resetAsync(); 498 499 while (mState == STATE_RESET_IN_PROGRESS) { 500 mCondition.wait(mLock); 501 } 502 503 mDurationUs = -1; 504 mPositionUs = -1; 505 mStartupSeekTimeUs = -1; 506 mLooping = false; 507 508 return OK; 509} 510 511status_t NuPlayerDriver::setLooping(int loop) { 512 mLooping = loop != 0; 513 return OK; 514} 515 516player_type NuPlayerDriver::playerType() { 517 return NU_PLAYER; 518} 519 520status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) { 521 if (reply == NULL) { 522 ALOGE("reply is a NULL pointer"); 523 return BAD_VALUE; 524 } 525 526 int32_t methodId; 527 status_t ret = request.readInt32(&methodId); 528 if (ret != OK) { 529 ALOGE("Failed to retrieve the requested method to invoke"); 530 return ret; 531 } 532 533 switch (methodId) { 534 case INVOKE_ID_SET_VIDEO_SCALING_MODE: 535 { 536 int mode = request.readInt32(); 537 return mPlayer->setVideoScalingMode(mode); 538 } 539 540 case INVOKE_ID_GET_TRACK_INFO: 541 { 542 return mPlayer->getTrackInfo(reply); 543 } 544 545 case INVOKE_ID_SELECT_TRACK: 546 { 547 int trackIndex = request.readInt32(); 548 int msec = 0; 549 // getCurrentPosition should always return OK 550 getCurrentPosition(&msec); 551 return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000ll); 552 } 553 554 case INVOKE_ID_UNSELECT_TRACK: 555 { 556 int trackIndex = request.readInt32(); 557 return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */); 558 } 559 560 case INVOKE_ID_GET_SELECTED_TRACK: 561 { 562 int32_t type = request.readInt32(); 563 return mPlayer->getSelectedTrack(type, reply); 564 } 565 566 default: 567 { 568 return INVALID_OPERATION; 569 } 570 } 571} 572 573void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) { 574 mPlayer->setAudioSink(audioSink); 575 mAudioSink = audioSink; 576} 577 578status_t NuPlayerDriver::setParameter( 579 int /* key */, const Parcel & /* request */) { 580 return INVALID_OPERATION; 581} 582 583status_t NuPlayerDriver::getParameter(int /* key */, Parcel * /* reply */) { 584 return INVALID_OPERATION; 585} 586 587status_t NuPlayerDriver::getMetadata( 588 const media::Metadata::Filter& /* ids */, Parcel *records) { 589 Mutex::Autolock autoLock(mLock); 590 591 using media::Metadata; 592 593 Metadata meta(records); 594 595 meta.appendBool( 596 Metadata::kPauseAvailable, 597 mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE); 598 599 meta.appendBool( 600 Metadata::kSeekBackwardAvailable, 601 mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD); 602 603 meta.appendBool( 604 Metadata::kSeekForwardAvailable, 605 mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD); 606 607 meta.appendBool( 608 Metadata::kSeekAvailable, 609 mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK); 610 611 return OK; 612} 613 614void NuPlayerDriver::notifyResetComplete() { 615 ALOGD("notifyResetComplete(%p)", this); 616 Mutex::Autolock autoLock(mLock); 617 618 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS); 619 mState = STATE_IDLE; 620 mCondition.broadcast(); 621} 622 623void NuPlayerDriver::notifySetSurfaceComplete() { 624 ALOGV("notifySetSurfaceComplete(%p)", this); 625 Mutex::Autolock autoLock(mLock); 626 627 CHECK(mSetSurfaceInProgress); 628 mSetSurfaceInProgress = false; 629 630 mCondition.broadcast(); 631} 632 633void NuPlayerDriver::notifyDuration(int64_t durationUs) { 634 Mutex::Autolock autoLock(mLock); 635 mDurationUs = durationUs; 636} 637 638void NuPlayerDriver::notifySeekComplete() { 639 ALOGV("notifySeekComplete(%p)", this); 640 Mutex::Autolock autoLock(mLock); 641 mSeekInProgress = false; 642 notifySeekComplete_l(); 643} 644 645void NuPlayerDriver::notifySeekComplete_l() { 646 bool wasSeeking = true; 647 if (mState == STATE_STOPPED_AND_PREPARING) { 648 wasSeeking = false; 649 mState = STATE_STOPPED_AND_PREPARED; 650 mCondition.broadcast(); 651 if (!mIsAsyncPrepare) { 652 // if we are preparing synchronously, no need to notify listener 653 return; 654 } 655 } else if (mState == STATE_STOPPED) { 656 // no need to notify listener 657 return; 658 } 659 notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED); 660} 661 662status_t NuPlayerDriver::dump( 663 int fd, const Vector<String16> & /* args */) const { 664 665 Vector<sp<AMessage> > trackStats; 666 mPlayer->getStats(&trackStats); 667 668 AString logString(" NuPlayer\n"); 669 char buf[256] = {0}; 670 671 for (size_t i = 0; i < trackStats.size(); ++i) { 672 const sp<AMessage> &stats = trackStats.itemAt(i); 673 674 AString mime; 675 if (stats->findString("mime", &mime)) { 676 snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str()); 677 logString.append(buf); 678 } 679 680 AString name; 681 if (stats->findString("component-name", &name)) { 682 snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str()); 683 logString.append(buf); 684 } 685 686 if (mime.startsWith("video/")) { 687 int32_t width, height; 688 if (stats->findInt32("width", &width) 689 && stats->findInt32("height", &height)) { 690 snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height); 691 logString.append(buf); 692 } 693 694 int64_t numFramesTotal = 0; 695 int64_t numFramesDropped = 0; 696 697 stats->findInt64("frames-total", &numFramesTotal); 698 stats->findInt64("frames-dropped-output", &numFramesDropped); 699 snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), " 700 "percentageDropped(%.2f%%)\n", 701 (long long)numFramesTotal, 702 (long long)numFramesDropped, 703 numFramesTotal == 0 704 ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal); 705 logString.append(buf); 706 } 707 } 708 709 ALOGI("%s", logString.c_str()); 710 711 if (fd >= 0) { 712 FILE *out = fdopen(dup(fd), "w"); 713 fprintf(out, "%s", logString.c_str()); 714 fclose(out); 715 out = NULL; 716 } 717 718 return OK; 719} 720 721void NuPlayerDriver::notifyListener( 722 int msg, int ext1, int ext2, const Parcel *in) { 723 Mutex::Autolock autoLock(mLock); 724 notifyListener_l(msg, ext1, ext2, in); 725} 726 727void NuPlayerDriver::notifyListener_l( 728 int msg, int ext1, int ext2, const Parcel *in) { 729 ALOGD("notifyListener_l(%p), (%d, %d, %d), loop setting(%d, %d)", 730 this, msg, ext1, ext2, mAutoLoop, mLooping); 731 switch (msg) { 732 case MEDIA_PLAYBACK_COMPLETE: 733 { 734 if (mState != STATE_RESET_IN_PROGRESS) { 735 if (mAutoLoop) { 736 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; 737 if (mAudioSink != NULL) { 738 streamType = mAudioSink->getAudioStreamType(); 739 } 740 if (streamType == AUDIO_STREAM_NOTIFICATION) { 741 ALOGW("disabling auto-loop for notification"); 742 mAutoLoop = false; 743 } 744 } 745 if (mLooping || mAutoLoop) { 746 mPlayer->seekToAsync(0); 747 if (mAudioSink != NULL) { 748 // The renderer has stopped the sink at the end in order to play out 749 // the last little bit of audio. If we're looping, we need to restart it. 750 mAudioSink->start(); 751 } 752 // don't send completion event when looping 753 return; 754 } 755 756 mPlayer->pause(); 757 mState = STATE_PAUSED; 758 } 759 // fall through 760 } 761 762 case MEDIA_ERROR: 763 { 764 mAtEOS = true; 765 break; 766 } 767 768 default: 769 break; 770 } 771 772 mLock.unlock(); 773 sendEvent(msg, ext1, ext2, in); 774 mLock.lock(); 775} 776 777void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) { 778 Mutex::Autolock autoLock(mLock); 779 780 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING); 781 782 mAsyncResult = err; 783 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE; 784 mCondition.broadcast(); 785} 786 787void NuPlayerDriver::notifyPrepareCompleted(status_t err) { 788 Mutex::Autolock autoLock(mLock); 789 790 if (mState != STATE_PREPARING) { 791 // We were preparing asynchronously when the client called 792 // reset(), we sent a premature "prepared" notification and 793 // then initiated the reset. This notification is stale. 794 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE); 795 return; 796 } 797 798 CHECK_EQ(mState, STATE_PREPARING); 799 800 mAsyncResult = err; 801 802 if (err == OK) { 803 // update state before notifying client, so that if client calls back into NuPlayerDriver 804 // in response, NuPlayerDriver has the right state 805 mState = STATE_PREPARED; 806 if (mIsAsyncPrepare) { 807 notifyListener_l(MEDIA_PREPARED); 808 } 809 } else { 810 mState = STATE_UNPREPARED; 811 if (mIsAsyncPrepare) { 812 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 813 } 814 } 815 816 sp<MetaData> meta = mPlayer->getFileMeta(); 817 int32_t loop; 818 if (meta != NULL 819 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) { 820 mAutoLoop = true; 821 } 822 823 mCondition.broadcast(); 824} 825 826void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) { 827 Mutex::Autolock autoLock(mLock); 828 829 mPlayerFlags = flags; 830} 831 832} // namespace android 833