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