1 /*
2 ** Copyright 2007, 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 "VorbisPlayer"
19 #include "utils/Log.h"
20
21 #include <stdio.h>
22 #include <assert.h>
23 #include <limits.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <sched.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29
30
31 #include "VorbisPlayer.h"
32
33 #ifdef HAVE_GETTID
myTid()34 static pid_t myTid() { return gettid(); }
35 #else
myTid()36 static pid_t myTid() { return getpid(); }
37 #endif
38
39 // ----------------------------------------------------------------------------
40
41 namespace android {
42
43 // ----------------------------------------------------------------------------
44
45 // TODO: Determine appropriate return codes
46 static status_t ERROR_NOT_OPEN = -1;
47 static status_t ERROR_OPEN_FAILED = -2;
48 static status_t ERROR_ALLOCATE_FAILED = -4;
49 static status_t ERROR_NOT_SUPPORTED = -8;
50 static status_t ERROR_NOT_READY = -16;
51 static status_t STATE_INIT = 0;
52 static status_t STATE_ERROR = 1;
53 static status_t STATE_OPEN = 2;
54
55
VorbisPlayer()56 VorbisPlayer::VorbisPlayer() :
57 mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR),
58 mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false),
59 mExit(false), mPaused(false), mRender(false), mRenderTid(-1)
60 {
61 LOGV("constructor\n");
62 memset(&mVorbisFile, 0, sizeof mVorbisFile);
63 }
64
onFirstRef()65 void VorbisPlayer::onFirstRef()
66 {
67 LOGV("onFirstRef");
68 // create playback thread
69 Mutex::Autolock l(mMutex);
70 createThreadEtc(renderThread, this, "vorbis decoder", ANDROID_PRIORITY_AUDIO);
71 mCondition.wait(mMutex);
72 if (mRenderTid > 0) {
73 LOGV("render thread(%d) started", mRenderTid);
74 mState = STATE_INIT;
75 }
76 }
77
initCheck()78 status_t VorbisPlayer::initCheck()
79 {
80 if (mState != STATE_ERROR) return NO_ERROR;
81 return ERROR_NOT_READY;
82 }
83
~VorbisPlayer()84 VorbisPlayer::~VorbisPlayer() {
85 LOGV("VorbisPlayer destructor\n");
86 release();
87 }
88
setDataSource(const char * path)89 status_t VorbisPlayer::setDataSource(const char* path)
90 {
91 return setdatasource(path, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX
92 }
93
setDataSource(int fd,int64_t offset,int64_t length)94 status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length)
95 {
96 return setdatasource(NULL, fd, offset, length);
97 }
98
vp_fread(void * buf,size_t size,size_t nmemb,void * me)99 size_t VorbisPlayer::vp_fread(void *buf, size_t size, size_t nmemb, void *me) {
100 VorbisPlayer *self = (VorbisPlayer*) me;
101
102 long curpos = vp_ftell(me);
103 while (nmemb != 0 && (curpos + size * nmemb) > self->mLength) {
104 nmemb--;
105 }
106 return fread(buf, size, nmemb, self->mFile);
107 }
108
vp_fseek(void * me,ogg_int64_t off,int whence)109 int VorbisPlayer::vp_fseek(void *me, ogg_int64_t off, int whence) {
110 VorbisPlayer *self = (VorbisPlayer*) me;
111 if (whence == SEEK_SET)
112 return fseek(self->mFile, off + self->mOffset, whence);
113 else if (whence == SEEK_CUR)
114 return fseek(self->mFile, off, whence);
115 else if (whence == SEEK_END)
116 return fseek(self->mFile, self->mOffset + self->mLength + off, SEEK_SET);
117 return -1;
118 }
119
vp_fclose(void * me)120 int VorbisPlayer::vp_fclose(void *me) {
121 LOGV("vp_fclose");
122 VorbisPlayer *self = (VorbisPlayer*) me;
123 int ret = fclose (self->mFile);
124 self->mFile = NULL;
125 return ret;
126 }
127
vp_ftell(void * me)128 long VorbisPlayer::vp_ftell(void *me) {
129 VorbisPlayer *self = (VorbisPlayer*) me;
130 return ftell(self->mFile) - self->mOffset;
131 }
132
setdatasource(const char * path,int fd,int64_t offset,int64_t length)133 status_t VorbisPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length)
134 {
135 LOGV("setDataSource url=%s, fd=%d\n", path, fd);
136
137 // file still open?
138 Mutex::Autolock l(mMutex);
139 if (mState == STATE_OPEN) {
140 reset_nosync();
141 }
142
143 // open file and set paused state
144 if (path) {
145 mFile = fopen(path, "r");
146 } else {
147 mFile = fdopen(dup(fd), "r");
148 }
149 if (mFile == NULL) {
150 return ERROR_OPEN_FAILED;
151 }
152
153 struct stat sb;
154 int ret;
155 if (path) {
156 ret = stat(path, &sb);
157 } else {
158 ret = fstat(fd, &sb);
159 }
160 if (ret != 0) {
161 mState = STATE_ERROR;
162 fclose(mFile);
163 return ERROR_OPEN_FAILED;
164 }
165 if (sb.st_size > (length + offset)) {
166 mLength = length;
167 } else {
168 mLength = sb.st_size - offset;
169 }
170
171 ov_callbacks callbacks = {
172 (size_t (*)(void *, size_t, size_t, void *)) vp_fread,
173 (int (*)(void *, ogg_int64_t, int)) vp_fseek,
174 (int (*)(void *)) vp_fclose,
175 (long (*)(void *)) vp_ftell
176 };
177
178 mOffset = offset;
179 fseek(mFile, offset, SEEK_SET);
180
181 int result = ov_open_callbacks(this, &mVorbisFile, NULL, 0, callbacks);
182 if (result < 0) {
183 LOGE("ov_open() failed: [%d]\n", (int)result);
184 mState = STATE_ERROR;
185 fclose(mFile);
186 return ERROR_OPEN_FAILED;
187 }
188
189 // look for the android loop tag (for ringtones)
190 char **ptr = ov_comment(&mVorbisFile,-1)->user_comments;
191 while(*ptr) {
192 // does the comment start with ANDROID_LOOP_TAG
193 if(strncmp(*ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) {
194 // read the value of the tag
195 char *val = *ptr + strlen(ANDROID_LOOP_TAG) + 1;
196 mAndroidLoop = (strncmp(val, "true", 4) == 0);
197 }
198 // we keep parsing even after finding one occurence of ANDROID_LOOP_TAG,
199 // as we could find another one (the tag might have been appended more than once).
200 ++ptr;
201 }
202 LOGV_IF(mAndroidLoop, "looped sound");
203
204 mState = STATE_OPEN;
205 return NO_ERROR;
206 }
207
prepare()208 status_t VorbisPlayer::prepare()
209 {
210 LOGV("prepare\n");
211 if (mState != STATE_OPEN ) {
212 return ERROR_NOT_OPEN;
213 }
214 return NO_ERROR;
215 }
216
prepareAsync()217 status_t VorbisPlayer::prepareAsync() {
218 LOGV("prepareAsync\n");
219 // can't hold the lock here because of the callback
220 // it's safe because we don't change state
221 if (mState != STATE_OPEN ) {
222 sendEvent(MEDIA_ERROR);
223 return NO_ERROR;
224 }
225 sendEvent(MEDIA_PREPARED);
226 return NO_ERROR;
227 }
228
start()229 status_t VorbisPlayer::start()
230 {
231 LOGV("start\n");
232 Mutex::Autolock l(mMutex);
233 if (mState != STATE_OPEN) {
234 return ERROR_NOT_OPEN;
235 }
236
237 mPaused = false;
238 mRender = true;
239
240 // wake up render thread
241 LOGV(" wakeup render thread\n");
242 mCondition.signal();
243 return NO_ERROR;
244 }
245
stop()246 status_t VorbisPlayer::stop()
247 {
248 LOGV("stop\n");
249 Mutex::Autolock l(mMutex);
250 if (mState != STATE_OPEN) {
251 return ERROR_NOT_OPEN;
252 }
253 mPaused = true;
254 mRender = false;
255 return NO_ERROR;
256 }
257
seekTo(int position)258 status_t VorbisPlayer::seekTo(int position)
259 {
260 LOGV("seekTo %d\n", position);
261 Mutex::Autolock l(mMutex);
262 if (mState != STATE_OPEN) {
263 return ERROR_NOT_OPEN;
264 }
265
266 int result = ov_time_seek(&mVorbisFile, position);
267 if (result != 0) {
268 LOGE("ov_time_seek() returned %d\n", result);
269 return result;
270 }
271 sendEvent(MEDIA_SEEK_COMPLETE);
272 return NO_ERROR;
273 }
274
pause()275 status_t VorbisPlayer::pause()
276 {
277 LOGV("pause\n");
278 Mutex::Autolock l(mMutex);
279 if (mState != STATE_OPEN) {
280 return ERROR_NOT_OPEN;
281 }
282 mPaused = true;
283 return NO_ERROR;
284 }
285
isPlaying()286 bool VorbisPlayer::isPlaying()
287 {
288 LOGV("isPlaying\n");
289 if (mState == STATE_OPEN) {
290 return mRender;
291 }
292 return false;
293 }
294
getCurrentPosition(int * position)295 status_t VorbisPlayer::getCurrentPosition(int* position)
296 {
297 LOGV("getCurrentPosition\n");
298 Mutex::Autolock l(mMutex);
299 if (mState != STATE_OPEN) {
300 LOGE("getCurrentPosition(): file not open");
301 return ERROR_NOT_OPEN;
302 }
303 *position = ov_time_tell(&mVorbisFile);
304 if (*position < 0) {
305 LOGE("getCurrentPosition(): ov_time_tell returned %d", *position);
306 return *position;
307 }
308 return NO_ERROR;
309 }
310
getDuration(int * duration)311 status_t VorbisPlayer::getDuration(int* duration)
312 {
313 LOGV("getDuration\n");
314 Mutex::Autolock l(mMutex);
315 if (mState != STATE_OPEN) {
316 return ERROR_NOT_OPEN;
317 }
318
319 int ret = ov_time_total(&mVorbisFile, -1);
320 if (ret == OV_EINVAL) {
321 return -1;
322 }
323
324 *duration = ret;
325 return NO_ERROR;
326 }
327
release()328 status_t VorbisPlayer::release()
329 {
330 LOGV("release\n");
331 Mutex::Autolock l(mMutex);
332 reset_nosync();
333
334 // TODO: timeout when thread won't exit
335 // wait for render thread to exit
336 if (mRenderTid > 0) {
337 mExit = true;
338 mCondition.signal();
339 mCondition.wait(mMutex);
340 }
341 return NO_ERROR;
342 }
343
reset()344 status_t VorbisPlayer::reset()
345 {
346 LOGV("reset\n");
347 Mutex::Autolock l(mMutex);
348 return reset_nosync();
349 }
350
351 // always call with lock held
reset_nosync()352 status_t VorbisPlayer::reset_nosync()
353 {
354 // close file
355 if (mFile != NULL) {
356 ov_clear(&mVorbisFile); // this also closes the FILE
357 if (mFile != NULL) {
358 LOGV("OOPS! Vorbis didn't close the file");
359 fclose(mFile);
360 mFile = NULL;
361 }
362 }
363 mState = STATE_ERROR;
364
365 mPlayTime = -1;
366 mDuration = -1;
367 mLoop = false;
368 mAndroidLoop = false;
369 mPaused = false;
370 mRender = false;
371 return NO_ERROR;
372 }
373
setLooping(int loop)374 status_t VorbisPlayer::setLooping(int loop)
375 {
376 LOGV("setLooping\n");
377 Mutex::Autolock l(mMutex);
378 mLoop = (loop != 0);
379 return NO_ERROR;
380 }
381
createOutputTrack()382 status_t VorbisPlayer::createOutputTrack() {
383 // open audio track
384 vorbis_info *vi = ov_info(&mVorbisFile, -1);
385
386 LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
387 vi->rate, vi->channels);
388 if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
389 LOGE("mAudioSink open failed");
390 return ERROR_OPEN_FAILED;
391 }
392 return NO_ERROR;
393 }
394
renderThread(void * p)395 int VorbisPlayer::renderThread(void* p) {
396 return ((VorbisPlayer*)p)->render();
397 }
398
399 #define AUDIOBUFFER_SIZE 4096
400
render()401 int VorbisPlayer::render() {
402 int result = -1;
403 int temp;
404 int current_section = 0;
405 bool audioStarted = false;
406
407 LOGV("render\n");
408
409 // allocate render buffer
410 mAudioBuffer = new char[AUDIOBUFFER_SIZE];
411 if (!mAudioBuffer) {
412 LOGE("mAudioBuffer allocate failed\n");
413 goto threadExit;
414 }
415
416 // let main thread know we're ready
417 {
418 Mutex::Autolock l(mMutex);
419 mRenderTid = myTid();
420 mCondition.signal();
421 }
422
423 while (1) {
424 long numread = 0;
425 {
426 Mutex::Autolock l(mMutex);
427
428 // pausing?
429 if (mPaused) {
430 if (mAudioSink->ready()) mAudioSink->pause();
431 mRender = false;
432 audioStarted = false;
433 }
434
435 // nothing to render, wait for client thread to wake us up
436 if (!mExit && !mRender) {
437 LOGV("render - signal wait\n");
438 mCondition.wait(mMutex);
439 LOGV("render - signal rx'd\n");
440 }
441 if (mExit) break;
442
443 // We could end up here if start() is called, and before we get a
444 // chance to run, the app calls stop() or reset(). Re-check render
445 // flag so we don't try to render in stop or reset state.
446 if (!mRender) continue;
447
448 // render vorbis data into the input buffer
449 numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section);
450 if (numread == 0) {
451 // end of file, do we need to loop?
452 // ...
453 if (mLoop || mAndroidLoop) {
454 ov_time_seek(&mVorbisFile, 0);
455 current_section = 0;
456 numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section);
457 } else {
458 mAudioSink->stop();
459 audioStarted = false;
460 mRender = false;
461 mPaused = true;
462 int endpos = ov_time_tell(&mVorbisFile);
463
464 LOGV("send MEDIA_PLAYBACK_COMPLETE");
465 sendEvent(MEDIA_PLAYBACK_COMPLETE);
466
467 // wait until we're started again
468 LOGV("playback complete - wait for signal");
469 mCondition.wait(mMutex);
470 LOGV("playback complete - signal rx'd");
471 if (mExit) break;
472
473 // if we're still at the end, restart from the beginning
474 if (mState == STATE_OPEN) {
475 int curpos = ov_time_tell(&mVorbisFile);
476 if (curpos == endpos) {
477 ov_time_seek(&mVorbisFile, 0);
478 }
479 current_section = 0;
480 numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section);
481 }
482 }
483 }
484 }
485
486 // codec returns negative number on error
487 if (numread < 0) {
488 LOGE("Error in Vorbis decoder");
489 sendEvent(MEDIA_ERROR);
490 break;
491 }
492
493 // create audio output track if necessary
494 if (!mAudioSink->ready()) {
495 LOGV("render - create output track\n");
496 if (createOutputTrack() != NO_ERROR)
497 break;
498 }
499
500 // Write data to the audio hardware
501 if ((temp = mAudioSink->write(mAudioBuffer, numread)) < 0) {
502 LOGE("Error in writing:%d",temp);
503 result = temp;
504 break;
505 }
506
507 // start audio output if necessary
508 if (!audioStarted && !mPaused && !mExit) {
509 LOGV("render - starting audio\n");
510 mAudioSink->start();
511 audioStarted = true;
512 }
513 }
514
515 threadExit:
516 mAudioSink.clear();
517 if (mAudioBuffer) {
518 delete [] mAudioBuffer;
519 mAudioBuffer = NULL;
520 }
521
522 // tell main thread goodbye
523 Mutex::Autolock l(mMutex);
524 mRenderTid = -1;
525 mCondition.signal();
526 return result;
527 }
528
529 } // end namespace android
530