• 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             mPlayer->pause();
259             break;
260 
261         default:
262             return INVALID_OPERATION;
263     }
264 
265     mState = STATE_PAUSED;
266 
267     return OK;
268 }
269 
isPlaying()270 bool NuPlayerDriver::isPlaying() {
271     return mState == STATE_RUNNING && !mAtEOS;
272 }
273 
seekTo(int msec)274 status_t NuPlayerDriver::seekTo(int msec) {
275     Mutex::Autolock autoLock(mLock);
276 
277     int64_t seekTimeUs = msec * 1000ll;
278 
279     switch (mState) {
280         case STATE_PREPARED:
281         {
282             mStartupSeekTimeUs = seekTimeUs;
283             break;
284         }
285 
286         case STATE_RUNNING:
287         case STATE_PAUSED:
288         {
289             mAtEOS = false;
290             mPlayer->seekToAsync(seekTimeUs);
291             break;
292         }
293 
294         default:
295             return INVALID_OPERATION;
296     }
297 
298     return OK;
299 }
300 
getCurrentPosition(int * msec)301 status_t NuPlayerDriver::getCurrentPosition(int *msec) {
302     Mutex::Autolock autoLock(mLock);
303 
304     if (mPositionUs < 0) {
305         *msec = 0;
306     } else {
307         *msec = (mPositionUs + 500ll) / 1000;
308     }
309 
310     return OK;
311 }
312 
getDuration(int * msec)313 status_t NuPlayerDriver::getDuration(int *msec) {
314     Mutex::Autolock autoLock(mLock);
315 
316     if (mDurationUs < 0) {
317         return UNKNOWN_ERROR;
318     }
319 
320     *msec = (mDurationUs + 500ll) / 1000;
321 
322     return OK;
323 }
324 
reset()325 status_t NuPlayerDriver::reset() {
326     Mutex::Autolock autoLock(mLock);
327 
328     switch (mState) {
329         case STATE_IDLE:
330             return OK;
331 
332         case STATE_SET_DATASOURCE_PENDING:
333         case STATE_RESET_IN_PROGRESS:
334             return INVALID_OPERATION;
335 
336         case STATE_PREPARING:
337         {
338             CHECK(mIsAsyncPrepare);
339 
340             notifyListener(MEDIA_PREPARED);
341             break;
342         }
343 
344         default:
345             break;
346     }
347 
348     mState = STATE_RESET_IN_PROGRESS;
349     mPlayer->resetAsync();
350 
351     while (mState == STATE_RESET_IN_PROGRESS) {
352         mCondition.wait(mLock);
353     }
354 
355     mDurationUs = -1;
356     mPositionUs = -1;
357     mStartupSeekTimeUs = -1;
358 
359     return OK;
360 }
361 
setLooping(int loop)362 status_t NuPlayerDriver::setLooping(int loop) {
363     return INVALID_OPERATION;
364 }
365 
playerType()366 player_type NuPlayerDriver::playerType() {
367     return NU_PLAYER;
368 }
369 
invoke(const Parcel & request,Parcel * reply)370 status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
371     if (reply == NULL) {
372         ALOGE("reply is a NULL pointer");
373         return BAD_VALUE;
374     }
375 
376     int32_t methodId;
377     status_t ret = request.readInt32(&methodId);
378     if (ret != OK) {
379         ALOGE("Failed to retrieve the requested method to invoke");
380         return ret;
381     }
382 
383     switch (methodId) {
384         case INVOKE_ID_SET_VIDEO_SCALING_MODE:
385         {
386             int mode = request.readInt32();
387             return mPlayer->setVideoScalingMode(mode);
388         }
389 
390         default:
391         {
392             return INVALID_OPERATION;
393         }
394     }
395 }
396 
setAudioSink(const sp<AudioSink> & audioSink)397 void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
398     mPlayer->setAudioSink(audioSink);
399 }
400 
setParameter(int key,const Parcel & request)401 status_t NuPlayerDriver::setParameter(int key, const Parcel &request) {
402     return INVALID_OPERATION;
403 }
404 
getParameter(int key,Parcel * reply)405 status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
406     return INVALID_OPERATION;
407 }
408 
getMetadata(const media::Metadata::Filter & ids,Parcel * records)409 status_t NuPlayerDriver::getMetadata(
410         const media::Metadata::Filter& ids, Parcel *records) {
411     Mutex::Autolock autoLock(mLock);
412 
413     using media::Metadata;
414 
415     Metadata meta(records);
416 
417     meta.appendBool(
418             Metadata::kPauseAvailable,
419             mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE);
420 
421     meta.appendBool(
422             Metadata::kSeekBackwardAvailable,
423             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD);
424 
425     meta.appendBool(
426             Metadata::kSeekForwardAvailable,
427             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD);
428 
429     meta.appendBool(
430             Metadata::kSeekAvailable,
431             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
432 
433     return OK;
434 }
435 
notifyResetComplete()436 void NuPlayerDriver::notifyResetComplete() {
437     Mutex::Autolock autoLock(mLock);
438 
439     CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
440     mState = STATE_IDLE;
441     mCondition.broadcast();
442 }
443 
notifySetSurfaceComplete()444 void NuPlayerDriver::notifySetSurfaceComplete() {
445     Mutex::Autolock autoLock(mLock);
446 
447     CHECK(mSetSurfaceInProgress);
448     mSetSurfaceInProgress = false;
449 
450     mCondition.broadcast();
451 }
452 
notifyDuration(int64_t durationUs)453 void NuPlayerDriver::notifyDuration(int64_t durationUs) {
454     Mutex::Autolock autoLock(mLock);
455     mDurationUs = durationUs;
456 }
457 
notifyPosition(int64_t positionUs)458 void NuPlayerDriver::notifyPosition(int64_t positionUs) {
459     Mutex::Autolock autoLock(mLock);
460     mPositionUs = positionUs;
461 }
462 
notifySeekComplete()463 void NuPlayerDriver::notifySeekComplete() {
464     notifyListener(MEDIA_SEEK_COMPLETE);
465 }
466 
notifyFrameStats(int64_t numFramesTotal,int64_t numFramesDropped)467 void NuPlayerDriver::notifyFrameStats(
468         int64_t numFramesTotal, int64_t numFramesDropped) {
469     Mutex::Autolock autoLock(mLock);
470     mNumFramesTotal = numFramesTotal;
471     mNumFramesDropped = numFramesDropped;
472 }
473 
dump(int fd,const Vector<String16> & args) const474 status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const {
475     Mutex::Autolock autoLock(mLock);
476 
477     FILE *out = fdopen(dup(fd), "w");
478 
479     fprintf(out, " NuPlayer\n");
480     fprintf(out, "  numFramesTotal(%lld), numFramesDropped(%lld), "
481                  "percentageDropped(%.2f)\n",
482                  mNumFramesTotal,
483                  mNumFramesDropped,
484                  mNumFramesTotal == 0
485                     ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
486 
487     fclose(out);
488     out = NULL;
489 
490     return OK;
491 }
492 
notifyListener(int msg,int ext1,int ext2)493 void NuPlayerDriver::notifyListener(int msg, int ext1, int ext2) {
494     if (msg == MEDIA_PLAYBACK_COMPLETE || msg == MEDIA_ERROR) {
495         mAtEOS = true;
496     }
497 
498     sendEvent(msg, ext1, ext2);
499 }
500 
notifySetDataSourceCompleted(status_t err)501 void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
502     Mutex::Autolock autoLock(mLock);
503 
504     CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
505 
506     mAsyncResult = err;
507     mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
508     mCondition.broadcast();
509 }
510 
notifyPrepareCompleted(status_t err)511 void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
512     Mutex::Autolock autoLock(mLock);
513 
514     if (mState != STATE_PREPARING) {
515         // We were preparing asynchronously when the client called
516         // reset(), we sent a premature "prepared" notification and
517         // then initiated the reset. This notification is stale.
518         CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
519         return;
520     }
521 
522     CHECK_EQ(mState, STATE_PREPARING);
523 
524     mAsyncResult = err;
525 
526     if (err == OK) {
527         if (mIsAsyncPrepare) {
528             notifyListener(MEDIA_PREPARED);
529         }
530         mState = STATE_PREPARED;
531     } else {
532         if (mIsAsyncPrepare) {
533             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
534         }
535         mState = STATE_UNPREPARED;
536     }
537 
538     mCondition.broadcast();
539 }
540 
notifyFlagsChanged(uint32_t flags)541 void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
542     Mutex::Autolock autoLock(mLock);
543 
544     mPlayerFlags = flags;
545 }
546 
547 }  // namespace android
548