NuPlayerDriver.cpp revision 666c8011c7ea96436b40912d94e6d6097dcfdaf6
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2010 The Android Open Source Project
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * you may not use this file except in compliance with the License.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You may obtain a copy of the License at
7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * See the License for the specific language governing permissions and
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * limitations under the License.
15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)//#define LOG_NDEBUG 0
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LOG_TAG "NuPlayerDriver"
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <inttypes.h>
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <utils/Log.h>
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "NuPlayerDriver.h"
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "NuPlayer.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "NuPlayerSource.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <media/stagefright/foundation/ADebug.h>
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <media/stagefright/foundation/ALooper.h>
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <media/stagefright/MetaData.h>
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace android {
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
33effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochNuPlayerDriver::NuPlayerDriver()
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : mState(STATE_IDLE),
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      mIsAsyncPrepare(false),
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      mAsyncResult(UNKNOWN_ERROR),
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      mSetSurfaceInProgress(false),
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      mDurationUs(-1),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mPositionUs(-1),
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      mNotifyTimeRealUs(-1),
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mPauseStartedTimeUs(-1),
42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      mNumFramesTotal(0),
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      mNumFramesDropped(0),
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mLooper(new ALooper),
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mPlayerFlags(0),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mAtEOS(false),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mLooping(false),
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      mStartupSeekTimeUs(-1) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mLooper->setName("NuPlayerDriver Looper");
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    mLooper->start(
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            false, /* runOnCallingThread */
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            true,  /* canCallJava */
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            PRIORITY_AUDIO);
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    mPlayer = new NuPlayer;
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    mLooper->registerHandler(mPlayer);
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    mPlayer->setDriver(this);
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)NuPlayerDriver::~NuPlayerDriver() {
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    mLooper->stop();
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)status_t NuPlayerDriver::initCheck() {
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return OK;
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)status_t NuPlayerDriver::setUID(uid_t uid) {
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mPlayer->setUID(uid);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return OK;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)status_t NuPlayerDriver::setDataSource(
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        const sp<IMediaHTTPService> &httpService,
7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        const char *url,
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        const KeyedVector<String8, String8> *headers) {
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    Mutex::Autolock autoLock(mLock);
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ALOGV("setDataSource: url=%s", url);
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (mState != STATE_IDLE) {
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        return INVALID_OPERATION;
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    mState = STATE_SET_DATASOURCE_PENDING;
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    mPlayer->setDataSourceAsync(httpService, url, headers);
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    while (mState == STATE_SET_DATASOURCE_PENDING) {
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        mCondition.wait(mLock);
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return mAsyncResult;
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Autolock autoLock(mLock);
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ALOGV("setDataSource: fd=%d", fd);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mState != STATE_IDLE) {
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return INVALID_OPERATION;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mState = STATE_SET_DATASOURCE_PENDING;
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    mPlayer->setDataSourceAsync(fd, offset, length);
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    while (mState == STATE_SET_DATASOURCE_PENDING) {
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        mCondition.wait(mLock);
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return mAsyncResult;
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Mutex::Autolock autoLock(mLock);
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    ALOGV("setDataSource: stream source");
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (mState != STATE_IDLE) {
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return INVALID_OPERATION;
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    mState = STATE_SET_DATASOURCE_PENDING;
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    mPlayer->setDataSourceAsync(source);
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    while (mState == STATE_SET_DATASOURCE_PENDING) {
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        mCondition.wait(mLock);
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return mAsyncResult;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)status_t NuPlayerDriver::setVideoSurfaceTexture(
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        const sp<IGraphicBufferProducer> &bufferProducer) {
138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    Mutex::Autolock autoLock(mLock);
139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (mSetSurfaceInProgress) {
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return INVALID_OPERATION;
1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    switch (mState) {
145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        case STATE_SET_DATASOURCE_PENDING:
146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        case STATE_RESET_IN_PROGRESS:
147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            return INVALID_OPERATION;
148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        default:
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            break;
151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    mSetSurfaceInProgress = true;
154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    mPlayer->setVideoSurfaceTextureAsync(bufferProducer);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (mSetSurfaceInProgress) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mCondition.wait(mLock);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return OK;
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)status_t NuPlayerDriver::prepare() {
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Mutex::Autolock autoLock(mLock);
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return prepare_l();
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)status_t NuPlayerDriver::prepare_l() {
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    switch (mState) {
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        case STATE_UNPREPARED:
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mState = STATE_PREPARING;
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            // Make sure we're not posting any notifications, success or
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // failure information is only communicated through our result
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // code.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mIsAsyncPrepare = false;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mPlayer->prepareAsync();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            while (mState == STATE_PREPARING) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                mCondition.wait(mLock);
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_STOPPED:
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // this is really just paused. handle as seek to start
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mAtEOS = false;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mState = STATE_STOPPED_AND_PREPARING;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mIsAsyncPrepare = false;
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            mPlayer->seekToAsync(0);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            while (mState == STATE_STOPPED_AND_PREPARING) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                mCondition.wait(mLock);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return (mState == STATE_STOPPED_AND_PREPARED) ? OK : UNKNOWN_ERROR;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            return INVALID_OPERATION;
19523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    };
19623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)status_t NuPlayerDriver::prepareAsync() {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Autolock autoLock(mLock);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (mState) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_UNPREPARED:
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mState = STATE_PREPARING;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mIsAsyncPrepare = true;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mPlayer->prepareAsync();
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            return OK;
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        case STATE_STOPPED:
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // this is really just paused. handle as seek to start
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mAtEOS = false;
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            mState = STATE_STOPPED_AND_PREPARING;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mIsAsyncPrepare = true;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mPlayer->seekToAsync(0);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return OK;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return INVALID_OPERATION;
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    };
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)status_t NuPlayerDriver::start() {
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    Mutex::Autolock autoLock(mLock);
2210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    switch (mState) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_UNPREPARED:
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            status_t err = prepare_l();
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            if (err != OK) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return err;
2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            }
2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            CHECK_EQ(mState, STATE_PREPARED);
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            // fall through
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_PREPARED:
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mAtEOS = false;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mPlayer->start();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (mStartupSeekTimeUs >= 0) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (mStartupSeekTimeUs == 0) {
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    notifySeekComplete_l();
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                } else {
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    mPlayer->seekToAsync(mStartupSeekTimeUs);
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                }
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                mStartupSeekTimeUs = -1;
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            }
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            break;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_RUNNING:
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (mAtEOS) {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                mPlayer->seekToAsync(0);
2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                mAtEOS = false;
2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                mPositionUs = -1;
2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            }
2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            break;
2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        }
2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        case STATE_PAUSED:
2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        case STATE_STOPPED_AND_PREPARED:
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        {
266a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            mPlayer->resume();
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            mPositionUs -= ALooper::GetNowUs() - mPauseStartedTimeUs;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            break;
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        default:
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return INVALID_OPERATION;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    mState = STATE_RUNNING;
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    mPauseStartedTimeUs = -1;
2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return OK;
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)status_t NuPlayerDriver::stop() {
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Mutex::Autolock autoLock(mLock);
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    switch (mState) {
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        case STATE_RUNNING:
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            mPlayer->pause();
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            // fall through
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        case STATE_PAUSED:
29023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            mState = STATE_STOPPED;
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            notifyListener_l(MEDIA_STOPPED);
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            break;
2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        case STATE_PREPARED:
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        case STATE_STOPPED:
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        case STATE_STOPPED_AND_PREPARING:
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        case STATE_STOPPED_AND_PREPARED:
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            mState = STATE_STOPPED;
29923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            break;
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
301e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        default:
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            return INVALID_OPERATION;
303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
304e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    setPauseStartedTimeIfNeeded();
30523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return OK;
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
30823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
30923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)status_t NuPlayerDriver::pause() {
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Mutex::Autolock autoLock(mLock);
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    switch (mState) {
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        case STATE_PAUSED:
31423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        case STATE_PREPARED:
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            return OK;
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
31723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        case STATE_RUNNING:
318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            setPauseStartedTimeIfNeeded();
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            mState = STATE_PAUSED;
32023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            notifyListener_l(MEDIA_PAUSED);
32123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            mPlayer->pause();
32223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            break;
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
32523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            return INVALID_OPERATION;
32623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
32723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return OK;
329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool NuPlayerDriver::isPlaying() {
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return mState == STATE_RUNNING && !mAtEOS;
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)status_t NuPlayerDriver::seekTo(int msec) {
3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Mutex::Autolock autoLock(mLock);
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64_t seekTimeUs = msec * 1000ll;
3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (mState) {
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case STATE_PREPARED:
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mStartupSeekTimeUs = seekTimeUs;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // pretend that the seek completed. It will actually happen when starting playback.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // TODO: actually perform the seek here, so the player is ready to go at the new
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // location
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            notifySeekComplete_l();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case STATE_RUNNING:
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case STATE_PAUSED:
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        {
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            mAtEOS = false;
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            // seeks can take a while, so we essentially paused
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            notifyListener_l(MEDIA_PAUSED);
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            mPlayer->seekToAsync(seekTimeUs);
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            break;
359effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        }
360effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
361effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        default:
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            return INVALID_OPERATION;
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    mPositionUs = seekTimeUs;
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    mNotifyTimeRealUs = -1;
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return OK;
368effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)status_t NuPlayerDriver::getCurrentPosition(int *msec) {
37123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    Mutex::Autolock autoLock(mLock);
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (mPositionUs < 0) {
374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        *msec = 0;
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else if (mNotifyTimeRealUs == -1) {
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        *msec = mPositionUs / 1000;
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        int64_t nowUs =
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                (isPlaying() ?  ALooper::GetNowUs() : mPauseStartedTimeUs);
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        *msec = (mPositionUs + nowUs - mNotifyTimeRealUs + 500ll) / 1000;
381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
382effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return OK;
384effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
386effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatus_t NuPlayerDriver::getDuration(int *msec) {
387effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    Mutex::Autolock autoLock(mLock);
388effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
389effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (mDurationUs < 0) {
390effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        return UNKNOWN_ERROR;
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
39323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    *msec = (mDurationUs + 500ll) / 1000;
39423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
39523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return OK;
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)status_t NuPlayerDriver::reset() {
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Mutex::Autolock autoLock(mLock);
400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    switch (mState) {
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case STATE_IDLE:
40323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            return OK;
40423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
40523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        case STATE_SET_DATASOURCE_PENDING:
406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case STATE_RESET_IN_PROGRESS:
407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            return INVALID_OPERATION;
408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
40923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        case STATE_PREPARING:
41023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        {
411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            CHECK(mIsAsyncPrepare);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
413            notifyListener_l(MEDIA_PREPARED);
414            break;
415        }
416
417        default:
418            break;
419    }
420
421    if (mState != STATE_STOPPED) {
422        notifyListener_l(MEDIA_STOPPED);
423    }
424
425    mState = STATE_RESET_IN_PROGRESS;
426    mPlayer->resetAsync();
427
428    while (mState == STATE_RESET_IN_PROGRESS) {
429        mCondition.wait(mLock);
430    }
431
432    mDurationUs = -1;
433    mPositionUs = -1;
434    mStartupSeekTimeUs = -1;
435    mLooping = false;
436
437    return OK;
438}
439
440status_t NuPlayerDriver::setLooping(int loop) {
441    mLooping = loop != 0;
442    return OK;
443}
444
445player_type NuPlayerDriver::playerType() {
446    return NU_PLAYER;
447}
448
449status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
450    if (reply == NULL) {
451        ALOGE("reply is a NULL pointer");
452        return BAD_VALUE;
453    }
454
455    int32_t methodId;
456    status_t ret = request.readInt32(&methodId);
457    if (ret != OK) {
458        ALOGE("Failed to retrieve the requested method to invoke");
459        return ret;
460    }
461
462    switch (methodId) {
463        case INVOKE_ID_SET_VIDEO_SCALING_MODE:
464        {
465            int mode = request.readInt32();
466            return mPlayer->setVideoScalingMode(mode);
467        }
468
469        case INVOKE_ID_GET_TRACK_INFO:
470        {
471            return mPlayer->getTrackInfo(reply);
472        }
473
474        case INVOKE_ID_SELECT_TRACK:
475        {
476            int trackIndex = request.readInt32();
477            return mPlayer->selectTrack(trackIndex, true /* select */);
478        }
479
480        case INVOKE_ID_UNSELECT_TRACK:
481        {
482            int trackIndex = request.readInt32();
483            return mPlayer->selectTrack(trackIndex, false /* select */);
484        }
485
486        case INVOKE_ID_GET_SELECTED_TRACK:
487        {
488            int32_t type = request.readInt32();
489            return mPlayer->getSelectedTrack(type, reply);
490        }
491
492        default:
493        {
494            return INVALID_OPERATION;
495        }
496    }
497}
498
499void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
500    mPlayer->setAudioSink(audioSink);
501}
502
503status_t NuPlayerDriver::setParameter(
504        int /* key */, const Parcel & /* request */) {
505    return INVALID_OPERATION;
506}
507
508status_t NuPlayerDriver::getParameter(int /* key */, Parcel * /* reply */) {
509    return INVALID_OPERATION;
510}
511
512status_t NuPlayerDriver::getMetadata(
513        const media::Metadata::Filter& /* ids */, Parcel *records) {
514    Mutex::Autolock autoLock(mLock);
515
516    using media::Metadata;
517
518    Metadata meta(records);
519
520    meta.appendBool(
521            Metadata::kPauseAvailable,
522            mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE);
523
524    meta.appendBool(
525            Metadata::kSeekBackwardAvailable,
526            mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD);
527
528    meta.appendBool(
529            Metadata::kSeekForwardAvailable,
530            mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD);
531
532    meta.appendBool(
533            Metadata::kSeekAvailable,
534            mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
535
536    return OK;
537}
538
539void NuPlayerDriver::notifyResetComplete() {
540    Mutex::Autolock autoLock(mLock);
541
542    CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
543    mState = STATE_IDLE;
544    mCondition.broadcast();
545}
546
547void NuPlayerDriver::notifySetSurfaceComplete() {
548    Mutex::Autolock autoLock(mLock);
549
550    CHECK(mSetSurfaceInProgress);
551    mSetSurfaceInProgress = false;
552
553    mCondition.broadcast();
554}
555
556void NuPlayerDriver::notifyDuration(int64_t durationUs) {
557    Mutex::Autolock autoLock(mLock);
558    mDurationUs = durationUs;
559}
560
561void NuPlayerDriver::notifyPosition(int64_t positionUs) {
562    Mutex::Autolock autoLock(mLock);
563    if (isPlaying()) {
564        mPositionUs = positionUs;
565        mNotifyTimeRealUs = ALooper::GetNowUs();
566    }
567}
568
569void NuPlayerDriver::notifySeekComplete() {
570    Mutex::Autolock autoLock(mLock);
571    notifySeekComplete_l();
572}
573
574void NuPlayerDriver::notifySeekComplete_l() {
575    bool wasSeeking = true;
576    if (mState == STATE_STOPPED_AND_PREPARING) {
577        wasSeeking = false;
578        mState = STATE_STOPPED_AND_PREPARED;
579        mCondition.broadcast();
580        if (!mIsAsyncPrepare) {
581            // if we are preparing synchronously, no need to notify listener
582            return;
583        }
584    } else if (mState == STATE_STOPPED) {
585        // no need to notify listener
586        return;
587    }
588    notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED);
589}
590
591void NuPlayerDriver::notifyFrameStats(
592        int64_t numFramesTotal, int64_t numFramesDropped) {
593    Mutex::Autolock autoLock(mLock);
594    mNumFramesTotal = numFramesTotal;
595    mNumFramesDropped = numFramesDropped;
596}
597
598status_t NuPlayerDriver::dump(
599        int fd, const Vector<String16> & /* args */) const {
600    Mutex::Autolock autoLock(mLock);
601
602    FILE *out = fdopen(dup(fd), "w");
603
604    fprintf(out, " NuPlayer\n");
605    fprintf(out, "  numFramesTotal(%" PRId64 "), numFramesDropped(%" PRId64 "), "
606                 "percentageDropped(%.2f)\n",
607                 mNumFramesTotal,
608                 mNumFramesDropped,
609                 mNumFramesTotal == 0
610                    ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
611
612    fclose(out);
613    out = NULL;
614
615    return OK;
616}
617
618void NuPlayerDriver::notifyListener(
619        int msg, int ext1, int ext2, const Parcel *in) {
620    Mutex::Autolock autoLock(mLock);
621    notifyListener_l(msg, ext1, ext2, in);
622}
623
624void NuPlayerDriver::notifyListener_l(
625        int msg, int ext1, int ext2, const Parcel *in) {
626    switch (msg) {
627        case MEDIA_PLAYBACK_COMPLETE:
628        {
629            if (mState != STATE_RESET_IN_PROGRESS) {
630                if (mLooping) {
631                    mPlayer->seekToAsync(0);
632                    break;
633                }
634
635                mPlayer->pause();
636                mState = STATE_PAUSED;
637            }
638            // fall through
639        }
640
641        case MEDIA_ERROR:
642        {
643            mAtEOS = true;
644            setPauseStartedTimeIfNeeded();
645            break;
646        }
647
648        default:
649            break;
650    }
651
652    mLock.unlock();
653    sendEvent(msg, ext1, ext2, in);
654    mLock.lock();
655}
656
657void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
658    Mutex::Autolock autoLock(mLock);
659
660    CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
661
662    mAsyncResult = err;
663    mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
664    mCondition.broadcast();
665}
666
667void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
668    Mutex::Autolock autoLock(mLock);
669
670    if (mState != STATE_PREPARING) {
671        // We were preparing asynchronously when the client called
672        // reset(), we sent a premature "prepared" notification and
673        // then initiated the reset. This notification is stale.
674        CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
675        return;
676    }
677
678    CHECK_EQ(mState, STATE_PREPARING);
679
680    mAsyncResult = err;
681
682    if (err == OK) {
683        // update state before notifying client, so that if client calls back into NuPlayerDriver
684        // in response, NuPlayerDriver has the right state
685        mState = STATE_PREPARED;
686        if (mIsAsyncPrepare) {
687            notifyListener_l(MEDIA_PREPARED);
688        }
689    } else {
690        mState = STATE_UNPREPARED;
691        if (mIsAsyncPrepare) {
692            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
693        }
694    }
695
696    mCondition.broadcast();
697}
698
699void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
700    Mutex::Autolock autoLock(mLock);
701
702    mPlayerFlags = flags;
703}
704
705void NuPlayerDriver::setPauseStartedTimeIfNeeded() {
706    if (mPauseStartedTimeUs == -1) {
707        mPauseStartedTimeUs = ALooper::GetNowUs();
708    }
709}
710
711}  // namespace android
712