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