NuPlayerDriver.cpp revision a4af2143ecbd630e946647c1b5f90fda8f61ebb3
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 <utils/Log.h>
20
21#include "NuPlayerDriver.h"
22
23#include "NuPlayer.h"
24
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/ALooper.h>
27
28namespace android {
29
30NuPlayerDriver::NuPlayerDriver()
31    : mResetInProgress(false),
32      mDurationUs(-1),
33      mPositionUs(-1),
34      mNumFramesTotal(0),
35      mNumFramesDropped(0),
36      mLooper(new ALooper),
37      mState(UNINITIALIZED),
38      mAtEOS(false),
39      mStartupSeekTimeUs(-1) {
40    mLooper->setName("NuPlayerDriver Looper");
41
42    mLooper->start(
43            false, /* runOnCallingThread */
44            true,  /* canCallJava */
45            PRIORITY_AUDIO);
46
47    mPlayer = new NuPlayer;
48    mLooper->registerHandler(mPlayer);
49
50    mPlayer->setDriver(this);
51}
52
53NuPlayerDriver::~NuPlayerDriver() {
54    mLooper->stop();
55}
56
57status_t NuPlayerDriver::initCheck() {
58    return OK;
59}
60
61status_t NuPlayerDriver::setUID(uid_t uid) {
62    mPlayer->setUID(uid);
63
64    return OK;
65}
66
67status_t NuPlayerDriver::setDataSource(
68        const char *url, const KeyedVector<String8, String8> *headers) {
69    CHECK_EQ((int)mState, (int)UNINITIALIZED);
70
71    mPlayer->setDataSource(url, headers);
72
73    mState = STOPPED;
74
75    return OK;
76}
77
78status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
79    return INVALID_OPERATION;
80}
81
82status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
83    CHECK_EQ((int)mState, (int)UNINITIALIZED);
84
85    mPlayer->setDataSource(source);
86
87    mState = STOPPED;
88
89    return OK;
90}
91
92status_t NuPlayerDriver::setVideoSurface(const sp<Surface> &surface) {
93    mPlayer->setVideoSurface(surface);
94
95    return OK;
96}
97
98status_t NuPlayerDriver::setVideoSurfaceTexture(
99        const sp<ISurfaceTexture> &surfaceTexture) {
100    mPlayer->setVideoSurfaceTexture(surfaceTexture);
101
102    return OK;
103}
104
105status_t NuPlayerDriver::prepare() {
106    return OK;
107}
108
109status_t NuPlayerDriver::prepareAsync() {
110    notifyListener(MEDIA_PREPARED);
111
112    return OK;
113}
114
115status_t NuPlayerDriver::start() {
116    switch (mState) {
117        case UNINITIALIZED:
118            return INVALID_OPERATION;
119        case STOPPED:
120        {
121            mAtEOS = false;
122            mPlayer->start();
123
124            if (mStartupSeekTimeUs >= 0) {
125                if (mStartupSeekTimeUs == 0) {
126                    notifySeekComplete();
127                } else {
128                    mPlayer->seekToAsync(mStartupSeekTimeUs);
129                }
130
131                mStartupSeekTimeUs = -1;
132            }
133
134            break;
135        }
136        case PLAYING:
137            return OK;
138        default:
139        {
140            CHECK_EQ((int)mState, (int)PAUSED);
141
142            mPlayer->resume();
143            break;
144        }
145    }
146
147    mState = PLAYING;
148
149    return OK;
150}
151
152status_t NuPlayerDriver::stop() {
153    return pause();
154}
155
156status_t NuPlayerDriver::pause() {
157    switch (mState) {
158        case UNINITIALIZED:
159            return INVALID_OPERATION;
160        case STOPPED:
161            return OK;
162        case PLAYING:
163            mPlayer->pause();
164            break;
165        default:
166        {
167            CHECK_EQ((int)mState, (int)PAUSED);
168            return OK;
169        }
170    }
171
172    mState = PAUSED;
173
174    return OK;
175}
176
177bool NuPlayerDriver::isPlaying() {
178    return mState == PLAYING && !mAtEOS;
179}
180
181status_t NuPlayerDriver::seekTo(int msec) {
182    int64_t seekTimeUs = msec * 1000ll;
183
184    switch (mState) {
185        case UNINITIALIZED:
186            return INVALID_OPERATION;
187        case STOPPED:
188        {
189            mStartupSeekTimeUs = seekTimeUs;
190            break;
191        }
192        case PLAYING:
193        case PAUSED:
194        {
195            mAtEOS = false;
196            mPlayer->seekToAsync(seekTimeUs);
197            break;
198        }
199
200        default:
201            TRESPASS();
202            break;
203    }
204
205    return OK;
206}
207
208status_t NuPlayerDriver::getCurrentPosition(int *msec) {
209    Mutex::Autolock autoLock(mLock);
210
211    if (mPositionUs < 0) {
212        *msec = 0;
213    } else {
214        *msec = (mPositionUs + 500ll) / 1000;
215    }
216
217    return OK;
218}
219
220status_t NuPlayerDriver::getDuration(int *msec) {
221    Mutex::Autolock autoLock(mLock);
222
223    if (mDurationUs < 0) {
224        *msec = 0;
225    } else {
226        *msec = (mDurationUs + 500ll) / 1000;
227    }
228
229    return OK;
230}
231
232status_t NuPlayerDriver::reset() {
233    Mutex::Autolock autoLock(mLock);
234    mResetInProgress = true;
235
236    mPlayer->resetAsync();
237
238    while (mResetInProgress) {
239        mCondition.wait(mLock);
240    }
241
242    mDurationUs = -1;
243    mPositionUs = -1;
244    mState = UNINITIALIZED;
245    mStartupSeekTimeUs = -1;
246
247    return OK;
248}
249
250status_t NuPlayerDriver::setLooping(int loop) {
251    return INVALID_OPERATION;
252}
253
254player_type NuPlayerDriver::playerType() {
255    return NU_PLAYER;
256}
257
258status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
259    return INVALID_OPERATION;
260}
261
262void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
263    mPlayer->setAudioSink(audioSink);
264}
265
266status_t NuPlayerDriver::setParameter(int key, const Parcel &request) {
267    return INVALID_OPERATION;
268}
269
270status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
271    return INVALID_OPERATION;
272}
273
274status_t NuPlayerDriver::getMetadata(
275        const media::Metadata::Filter& ids, Parcel *records) {
276    return INVALID_OPERATION;
277}
278
279void NuPlayerDriver::notifyResetComplete() {
280    Mutex::Autolock autoLock(mLock);
281    CHECK(mResetInProgress);
282    mResetInProgress = false;
283    mCondition.broadcast();
284}
285
286void NuPlayerDriver::notifyDuration(int64_t durationUs) {
287    Mutex::Autolock autoLock(mLock);
288    mDurationUs = durationUs;
289}
290
291void NuPlayerDriver::notifyPosition(int64_t positionUs) {
292    Mutex::Autolock autoLock(mLock);
293    mPositionUs = positionUs;
294}
295
296void NuPlayerDriver::notifySeekComplete() {
297    notifyListener(MEDIA_SEEK_COMPLETE);
298}
299
300void NuPlayerDriver::notifyFrameStats(
301        int64_t numFramesTotal, int64_t numFramesDropped) {
302    Mutex::Autolock autoLock(mLock);
303    mNumFramesTotal = numFramesTotal;
304    mNumFramesDropped = numFramesDropped;
305}
306
307status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const {
308    Mutex::Autolock autoLock(mLock);
309
310    FILE *out = fdopen(dup(fd), "w");
311
312    fprintf(out, " NuPlayer\n");
313    fprintf(out, "  numFramesTotal(%lld), numFramesDropped(%lld), "
314                 "percentageDropped(%.2f)\n",
315                 mNumFramesTotal,
316                 mNumFramesDropped,
317                 mNumFramesTotal == 0
318                    ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
319
320    fclose(out);
321    out = NULL;
322
323    return OK;
324}
325
326void NuPlayerDriver::notifyListener(int msg, int ext1, int ext2) {
327    if (msg == MEDIA_PLAYBACK_COMPLETE || msg == MEDIA_ERROR) {
328        mAtEOS = true;
329    }
330
331    sendEvent(msg, ext1, ext2);
332}
333
334}  // namespace android
335