NuPlayerDriver.cpp revision 57cea553cb19235553463412db5ad04c99835411
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#include "NuPlayerSource.h"
25
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/foundation/ALooper.h>
28#include <media/stagefright/MetaData.h>
29
30namespace android {
31
32NuPlayerDriver::NuPlayerDriver()
33    : mState(STATE_IDLE),
34      mAsyncResult(UNKNOWN_ERROR),
35      mSetSurfaceInProgress(false),
36      mDurationUs(-1),
37      mPositionUs(-1),
38      mNumFramesTotal(0),
39      mNumFramesDropped(0),
40      mLooper(new ALooper),
41      mPlayerFlags(0),
42      mAtEOS(false),
43      mStartupSeekTimeUs(-1) {
44    mLooper->setName("NuPlayerDriver Looper");
45
46    mLooper->start(
47            false, /* runOnCallingThread */
48            true,  /* canCallJava */
49            PRIORITY_AUDIO);
50
51    mPlayer = new NuPlayer;
52    mLooper->registerHandler(mPlayer);
53
54    mPlayer->setDriver(this);
55}
56
57NuPlayerDriver::~NuPlayerDriver() {
58    mLooper->stop();
59}
60
61status_t NuPlayerDriver::initCheck() {
62    return OK;
63}
64
65status_t NuPlayerDriver::setUID(uid_t uid) {
66    mPlayer->setUID(uid);
67
68    return OK;
69}
70
71status_t NuPlayerDriver::setDataSource(
72        const char *url, const KeyedVector<String8, String8> *headers) {
73    Mutex::Autolock autoLock(mLock);
74
75    if (mState != STATE_IDLE) {
76        return INVALID_OPERATION;
77    }
78
79    mState = STATE_SET_DATASOURCE_PENDING;
80
81    mPlayer->setDataSourceAsync(url, headers);
82
83    while (mState == STATE_SET_DATASOURCE_PENDING) {
84        mCondition.wait(mLock);
85    }
86
87    return mAsyncResult;
88}
89
90status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
91    Mutex::Autolock autoLock(mLock);
92
93    if (mState != STATE_IDLE) {
94        return INVALID_OPERATION;
95    }
96
97    mState = STATE_SET_DATASOURCE_PENDING;
98
99    mPlayer->setDataSourceAsync(fd, offset, length);
100
101    while (mState == STATE_SET_DATASOURCE_PENDING) {
102        mCondition.wait(mLock);
103    }
104
105    return mAsyncResult;
106}
107
108status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
109    Mutex::Autolock autoLock(mLock);
110
111    if (mState != STATE_IDLE) {
112        return INVALID_OPERATION;
113    }
114
115    mState = STATE_SET_DATASOURCE_PENDING;
116
117    mPlayer->setDataSourceAsync(source);
118
119    while (mState == STATE_SET_DATASOURCE_PENDING) {
120        mCondition.wait(mLock);
121    }
122
123    return mAsyncResult;
124}
125
126status_t NuPlayerDriver::setVideoSurfaceTexture(
127        const sp<IGraphicBufferProducer> &bufferProducer) {
128    Mutex::Autolock autoLock(mLock);
129
130    if (mSetSurfaceInProgress) {
131        return INVALID_OPERATION;
132    }
133
134    switch (mState) {
135        case STATE_SET_DATASOURCE_PENDING:
136        case STATE_RESET_IN_PROGRESS:
137            return INVALID_OPERATION;
138
139        default:
140            break;
141    }
142
143    mSetSurfaceInProgress = true;
144
145    mPlayer->setVideoSurfaceTextureAsync(bufferProducer);
146
147    while (mSetSurfaceInProgress) {
148        mCondition.wait(mLock);
149    }
150
151    return OK;
152}
153
154status_t NuPlayerDriver::prepare() {
155    Mutex::Autolock autoLock(mLock);
156    return prepare_l();
157}
158
159status_t NuPlayerDriver::prepare_l() {
160    switch (mState) {
161        case STATE_UNPREPARED:
162            mState = STATE_PREPARING;
163            mPlayer->prepareAsync();
164            while (mState == STATE_PREPARING) {
165                mCondition.wait(mLock);
166            }
167            return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR;
168        default:
169            return INVALID_OPERATION;
170    };
171}
172
173status_t NuPlayerDriver::prepareAsync() {
174    Mutex::Autolock autoLock(mLock);
175
176    switch (mState) {
177        case STATE_UNPREPARED:
178            mState = STATE_PREPARING;
179            mPlayer->prepareAsync();
180            return OK;
181        default:
182            return INVALID_OPERATION;
183    };
184}
185
186status_t NuPlayerDriver::start() {
187    Mutex::Autolock autoLock(mLock);
188
189    switch (mState) {
190        case STATE_UNPREPARED:
191        {
192            status_t err = prepare_l();
193
194            if (err != OK) {
195                return err;
196            }
197
198            CHECK_EQ(mState, STATE_PREPARED);
199
200            // fall through
201        }
202
203        case STATE_PREPARED:
204        {
205            mAtEOS = false;
206            mPlayer->start();
207
208            if (mStartupSeekTimeUs >= 0) {
209                if (mStartupSeekTimeUs == 0) {
210                    notifySeekComplete();
211                } else {
212                    mPlayer->seekToAsync(mStartupSeekTimeUs);
213                }
214
215                mStartupSeekTimeUs = -1;
216            }
217            break;
218        }
219
220        case STATE_RUNNING:
221            break;
222
223        case STATE_PAUSED:
224        {
225            mPlayer->resume();
226            break;
227        }
228
229        default:
230            return INVALID_OPERATION;
231    }
232
233    mState = STATE_RUNNING;
234
235    return OK;
236}
237
238status_t NuPlayerDriver::stop() {
239    return pause();
240}
241
242status_t NuPlayerDriver::pause() {
243    Mutex::Autolock autoLock(mLock);
244
245    switch (mState) {
246        case STATE_PAUSED:
247        case STATE_PREPARED:
248            return OK;
249
250        case STATE_RUNNING:
251            mPlayer->pause();
252            break;
253
254        default:
255            return INVALID_OPERATION;
256    }
257
258    mState = STATE_PAUSED;
259
260    return OK;
261}
262
263bool NuPlayerDriver::isPlaying() {
264    return mState == STATE_RUNNING && !mAtEOS;
265}
266
267status_t NuPlayerDriver::seekTo(int msec) {
268    Mutex::Autolock autoLock(mLock);
269
270    int64_t seekTimeUs = msec * 1000ll;
271
272    switch (mState) {
273        case STATE_PREPARED:
274        {
275            mStartupSeekTimeUs = seekTimeUs;
276            break;
277        }
278
279        case STATE_RUNNING:
280        case STATE_PAUSED:
281        {
282            mAtEOS = false;
283            mPlayer->seekToAsync(seekTimeUs);
284            break;
285        }
286
287        default:
288            return INVALID_OPERATION;
289    }
290
291    return OK;
292}
293
294status_t NuPlayerDriver::getCurrentPosition(int *msec) {
295    Mutex::Autolock autoLock(mLock);
296
297    if (mPositionUs < 0) {
298        *msec = 0;
299    } else {
300        *msec = (mPositionUs + 500ll) / 1000;
301    }
302
303    return OK;
304}
305
306status_t NuPlayerDriver::getDuration(int *msec) {
307    Mutex::Autolock autoLock(mLock);
308
309    if (mDurationUs < 0) {
310        *msec = 0;
311    } else {
312        *msec = (mDurationUs + 500ll) / 1000;
313    }
314
315    return OK;
316}
317
318status_t NuPlayerDriver::reset() {
319    Mutex::Autolock autoLock(mLock);
320
321    switch (mState) {
322        case STATE_IDLE:
323            return OK;
324
325        case STATE_SET_DATASOURCE_PENDING:
326        case STATE_RESET_IN_PROGRESS:
327            return INVALID_OPERATION;
328
329        default:
330            break;
331    }
332
333    mState = STATE_RESET_IN_PROGRESS;
334    mPlayer->resetAsync();
335
336    while (mState == STATE_RESET_IN_PROGRESS) {
337        mCondition.wait(mLock);
338    }
339
340    mDurationUs = -1;
341    mPositionUs = -1;
342    mStartupSeekTimeUs = -1;
343
344    return OK;
345}
346
347status_t NuPlayerDriver::setLooping(int loop) {
348    return INVALID_OPERATION;
349}
350
351player_type NuPlayerDriver::playerType() {
352    return NU_PLAYER;
353}
354
355status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
356    if (reply == NULL) {
357        ALOGE("reply is a NULL pointer");
358        return BAD_VALUE;
359    }
360
361    int32_t methodId;
362    status_t ret = request.readInt32(&methodId);
363    if (ret != OK) {
364        ALOGE("Failed to retrieve the requested method to invoke");
365        return ret;
366    }
367
368    switch (methodId) {
369        case INVOKE_ID_SET_VIDEO_SCALING_MODE:
370        {
371            int mode = request.readInt32();
372            return mPlayer->setVideoScalingMode(mode);
373        }
374        default:
375        {
376            return INVALID_OPERATION;
377        }
378    }
379}
380
381void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
382    mPlayer->setAudioSink(audioSink);
383}
384
385status_t NuPlayerDriver::setParameter(int key, const Parcel &request) {
386    return INVALID_OPERATION;
387}
388
389status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
390    return INVALID_OPERATION;
391}
392
393status_t NuPlayerDriver::getMetadata(
394        const media::Metadata::Filter& ids, Parcel *records) {
395    Mutex::Autolock autoLock(mLock);
396
397    using media::Metadata;
398
399    Metadata meta(records);
400
401    meta.appendBool(
402            Metadata::kPauseAvailable,
403            mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE);
404
405    meta.appendBool(
406            Metadata::kSeekBackwardAvailable,
407            mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD);
408
409    meta.appendBool(
410            Metadata::kSeekForwardAvailable,
411            mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD);
412
413    meta.appendBool(
414            Metadata::kSeekAvailable,
415            mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
416
417    return OK;
418}
419
420void NuPlayerDriver::notifyResetComplete() {
421    Mutex::Autolock autoLock(mLock);
422
423    CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
424    mState = STATE_IDLE;
425    mCondition.broadcast();
426}
427
428void NuPlayerDriver::notifySetSurfaceComplete() {
429    Mutex::Autolock autoLock(mLock);
430
431    CHECK(mSetSurfaceInProgress);
432    mSetSurfaceInProgress = false;
433
434    mCondition.broadcast();
435}
436
437void NuPlayerDriver::notifyDuration(int64_t durationUs) {
438    Mutex::Autolock autoLock(mLock);
439    mDurationUs = durationUs;
440}
441
442void NuPlayerDriver::notifyPosition(int64_t positionUs) {
443    Mutex::Autolock autoLock(mLock);
444    mPositionUs = positionUs;
445}
446
447void NuPlayerDriver::notifySeekComplete() {
448    notifyListener(MEDIA_SEEK_COMPLETE);
449}
450
451void NuPlayerDriver::notifyFrameStats(
452        int64_t numFramesTotal, int64_t numFramesDropped) {
453    Mutex::Autolock autoLock(mLock);
454    mNumFramesTotal = numFramesTotal;
455    mNumFramesDropped = numFramesDropped;
456}
457
458status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const {
459    Mutex::Autolock autoLock(mLock);
460
461    FILE *out = fdopen(dup(fd), "w");
462
463    fprintf(out, " NuPlayer\n");
464    fprintf(out, "  numFramesTotal(%lld), numFramesDropped(%lld), "
465                 "percentageDropped(%.2f)\n",
466                 mNumFramesTotal,
467                 mNumFramesDropped,
468                 mNumFramesTotal == 0
469                    ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
470
471    fclose(out);
472    out = NULL;
473
474    return OK;
475}
476
477void NuPlayerDriver::notifyListener(int msg, int ext1, int ext2) {
478    if (msg == MEDIA_PLAYBACK_COMPLETE || msg == MEDIA_ERROR) {
479        mAtEOS = true;
480    }
481
482    sendEvent(msg, ext1, ext2);
483}
484
485void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
486    Mutex::Autolock autoLock(mLock);
487
488    CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
489
490    mAsyncResult = err;
491    mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
492    mCondition.broadcast();
493}
494
495void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
496    Mutex::Autolock autoLock(mLock);
497
498    CHECK_EQ(mState, STATE_PREPARING);
499
500    mAsyncResult = err;
501
502    if (err == OK) {
503        notifyListener(MEDIA_PREPARED);
504        mState = STATE_PREPARED;
505    } else {
506        mState = STATE_UNPREPARED;
507    }
508
509    mCondition.broadcast();
510}
511
512void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
513    Mutex::Autolock autoLock(mLock);
514
515    mPlayerFlags = flags;
516}
517
518}  // namespace android
519