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