blob: 95001c69a084ecb5acfe675fd6508dd0b2aa5f6b [file] [log] [blame]
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18// Proxy for media player implementations
19
20//#define LOG_NDEBUG 0
21#define LOG_TAG "MediaPlayerService"
22#include <utils/Log.h>
23
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <dirent.h>
27#include <unistd.h>
28
29#include <string.h>
30#include <cutils/atomic.h>
31
32#include <android_runtime/ActivityManager.h>
33#include <utils/IPCThreadState.h>
34#include <utils/IServiceManager.h>
35#include <utils/MemoryHeapBase.h>
36#include <utils/MemoryBase.h>
37#include <cutils/properties.h>
38
39#include <media/MediaPlayerInterface.h>
40#include <media/mediarecorder.h>
41#include <media/MediaMetadataRetrieverInterface.h>
42#include <media/AudioTrack.h>
43
44#include "MediaRecorderClient.h"
45#include "MediaPlayerService.h"
46#include "MetadataRetrieverClient.h"
47
48#include "MidiFile.h"
49#include "VorbisPlayer.h"
50#include <media/PVPlayer.h>
51
52/* desktop Linux needs a little help with gettid() */
53#if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
54#define __KERNEL__
55# include <linux/unistd.h>
56#ifdef _syscall0
57_syscall0(pid_t,gettid)
58#else
59pid_t gettid() { return syscall(__NR_gettid);}
60#endif
61#undef __KERNEL__
62#endif
63
64
65namespace android {
66
67// TODO: Temp hack until we can register players
68typedef struct {
69 const char *extension;
70 const player_type playertype;
71} extmap;
72extmap FILE_EXTS [] = {
73 {".mid", SONIVOX_PLAYER},
74 {".midi", SONIVOX_PLAYER},
75 {".smf", SONIVOX_PLAYER},
76 {".xmf", SONIVOX_PLAYER},
77 {".imy", SONIVOX_PLAYER},
78 {".rtttl", SONIVOX_PLAYER},
79 {".rtx", SONIVOX_PLAYER},
80 {".ota", SONIVOX_PLAYER},
81 {".ogg", VORBIS_PLAYER},
82 {".oga", VORBIS_PLAYER},
83};
84
85// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
86/* static */ const uint32_t MediaPlayerService::AudioOutput::kAudioVideoDelayMs = 96;
87/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
88/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
89
90void MediaPlayerService::instantiate() {
91 defaultServiceManager()->addService(
92 String16("media.player"), new MediaPlayerService());
93}
94
95MediaPlayerService::MediaPlayerService()
96{
97 LOGV("MediaPlayerService created");
98 mNextConnId = 1;
99}
100
101MediaPlayerService::~MediaPlayerService()
102{
103 LOGV("MediaPlayerService destroyed");
104}
105
106sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
107{
Jean-Baptiste Queru6c5b2102009-03-21 11:40:18 -0700108#ifndef NO_OPENCORE
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800109 sp<MediaRecorderClient> recorder = new MediaRecorderClient(pid);
Jean-Baptiste Queru6c5b2102009-03-21 11:40:18 -0700110#else
111 sp<MediaRecorderClient> recorder = NULL;
112#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800113 LOGV("Create new media recorder client from pid %d", pid);
114 return recorder;
115}
116
117sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)
118{
119 sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
120 LOGV("Create new media retriever from pid %d", pid);
121 return retriever;
122}
123
124sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
125{
126 int32_t connId = android_atomic_inc(&mNextConnId);
127 sp<Client> c = new Client(this, pid, connId, client);
128 LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
129 if (NO_ERROR != c->setDataSource(url))
130 {
131 c.clear();
132 return c;
133 }
134 wp<Client> w = c;
135 Mutex::Autolock lock(mLock);
136 mClients.add(w);
137 return c;
138}
139
140sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
141 int fd, int64_t offset, int64_t length)
142{
143 int32_t connId = android_atomic_inc(&mNextConnId);
144 sp<Client> c = new Client(this, pid, connId, client);
145 LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld",
146 connId, pid, fd, offset, length);
147 if (NO_ERROR != c->setDataSource(fd, offset, length)) {
148 c.clear();
149 } else {
150 wp<Client> w = c;
151 Mutex::Autolock lock(mLock);
152 mClients.add(w);
153 }
154 ::close(fd);
155 return c;
156}
157
158status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
159{
160 const size_t SIZE = 256;
161 char buffer[SIZE];
162 String8 result;
163
164 result.append(" AudioCache\n");
165 if (mHeap != 0) {
166 snprintf(buffer, 255, " heap base(%p), size(%d), flags(%d), device(%s)\n",
167 mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice());
168 result.append(buffer);
169 }
170 snprintf(buffer, 255, " msec per frame(%f), channel count(%d), format(%d), frame count(%ld)\n",
171 mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
172 result.append(buffer);
173 snprintf(buffer, 255, " sample rate(%d), size(%d), error(%d), command complete(%s)\n",
174 mSampleRate, mSize, mError, mCommandComplete?"true":"false");
175 result.append(buffer);
176 ::write(fd, result.string(), result.size());
177 return NO_ERROR;
178}
179
180status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
181{
182 const size_t SIZE = 256;
183 char buffer[SIZE];
184 String8 result;
185
186 result.append(" AudioOutput\n");
187 snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n",
188 mStreamType, mLeftVolume, mRightVolume);
189 result.append(buffer);
190 snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
191 mMsecsPerFrame, mLatency);
192 result.append(buffer);
193 ::write(fd, result.string(), result.size());
194 if (mTrack != 0) {
195 mTrack->dump(fd, args);
196 }
197 return NO_ERROR;
198}
199
200status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args) const
201{
202 const size_t SIZE = 256;
203 char buffer[SIZE];
204 String8 result;
205 result.append(" Client\n");
206 snprintf(buffer, 255, " pid(%d), connId(%d), status(%d), looping(%s)\n",
207 mPid, mConnId, mStatus, mLoop?"true": "false");
208 result.append(buffer);
209 write(fd, result.string(), result.size());
210 if (mAudioOutput != 0) {
211 mAudioOutput->dump(fd, args);
212 }
213 write(fd, "\n", 1);
214 return NO_ERROR;
215}
216
217static int myTid() {
218#ifdef HAVE_GETTID
219 return gettid();
220#else
221 return getpid();
222#endif
223}
224
225#if defined(__arm__)
226extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
227 size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
228extern "C" void free_malloc_leak_info(uint8_t* info);
229
230void memStatus(int fd, const Vector<String16>& args)
231{
232 const size_t SIZE = 256;
233 char buffer[SIZE];
234 String8 result;
235
236 typedef struct {
237 size_t size;
238 size_t dups;
239 intptr_t * backtrace;
240 } AllocEntry;
241
242 uint8_t *info = NULL;
243 size_t overallSize = 0;
244 size_t infoSize = 0;
245 size_t totalMemory = 0;
246 size_t backtraceSize = 0;
247
248 get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
249 if (info) {
250 uint8_t *ptr = info;
251 size_t count = overallSize / infoSize;
252
253 snprintf(buffer, SIZE, " Allocation count %i\n", count);
254 result.append(buffer);
255
256 AllocEntry * entries = new AllocEntry[count];
257
258 for (size_t i = 0; i < count; i++) {
259 // Each entry should be size_t, size_t, intptr_t[backtraceSize]
260 AllocEntry *e = &entries[i];
261
262 e->size = *reinterpret_cast<size_t *>(ptr);
263 ptr += sizeof(size_t);
264
265 e->dups = *reinterpret_cast<size_t *>(ptr);
266 ptr += sizeof(size_t);
267
268 e->backtrace = reinterpret_cast<intptr_t *>(ptr);
269 ptr += sizeof(intptr_t) * backtraceSize;
270 }
271
272 // Now we need to sort the entries. They come sorted by size but
273 // not by stack trace which causes problems using diff.
274 bool moved;
275 do {
276 moved = false;
277 for (size_t i = 0; i < (count - 1); i++) {
278 AllocEntry *e1 = &entries[i];
279 AllocEntry *e2 = &entries[i+1];
280
281 bool swap = e1->size < e2->size;
282 if (e1->size == e2->size) {
283 for(size_t j = 0; j < backtraceSize; j++) {
284 if (e1->backtrace[j] == e2->backtrace[j]) {
285 continue;
286 }
287 swap = e1->backtrace[j] < e2->backtrace[j];
288 break;
289 }
290 }
291 if (swap) {
292 AllocEntry t = entries[i];
293 entries[i] = entries[i+1];
294 entries[i+1] = t;
295 moved = true;
296 }
297 }
298 } while (moved);
299
300 for (size_t i = 0; i < count; i++) {
301 AllocEntry *e = &entries[i];
302
303 snprintf(buffer, SIZE, "size %8i, dup %4i", e->size, e->dups);
304 result.append(buffer);
305 for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
306 if (ct) {
307 result.append(", ");
308 }
309 snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
310 result.append(buffer);
311 }
312 result.append("\n");
313 }
314
315 delete[] entries;
316 free_malloc_leak_info(info);
317 }
318
319 write(fd, result.string(), result.size());
320}
321#endif
322
323status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
324{
325 const size_t SIZE = 256;
326 char buffer[SIZE];
327 String8 result;
328 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
329 snprintf(buffer, SIZE, "Permission Denial: "
330 "can't dump MediaPlayerService from pid=%d, uid=%d\n",
331 IPCThreadState::self()->getCallingPid(),
332 IPCThreadState::self()->getCallingUid());
333 result.append(buffer);
334 } else {
335 Mutex::Autolock lock(mLock);
336 for (int i = 0, n = mClients.size(); i < n; ++i) {
337 sp<Client> c = mClients[i].promote();
338 if (c != 0) c->dump(fd, args);
339 }
340 result.append(" Files opened and/or mapped:\n");
341 snprintf(buffer, SIZE, "/proc/%d/maps", myTid());
342 FILE *f = fopen(buffer, "r");
343 if (f) {
344 while (!feof(f)) {
345 fgets(buffer, SIZE, f);
346 if (strstr(buffer, " /sdcard/") ||
347 strstr(buffer, " /system/sounds/") ||
348 strstr(buffer, " /system/media/")) {
349 result.append(" ");
350 result.append(buffer);
351 }
352 }
353 fclose(f);
354 } else {
355 result.append("couldn't open ");
356 result.append(buffer);
357 result.append("\n");
358 }
359
360 snprintf(buffer, SIZE, "/proc/%d/fd", myTid());
361 DIR *d = opendir(buffer);
362 if (d) {
363 struct dirent *ent;
364 while((ent = readdir(d)) != NULL) {
365 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
366 snprintf(buffer, SIZE, "/proc/%d/fd/%s", myTid(), ent->d_name);
367 struct stat s;
368 if (lstat(buffer, &s) == 0) {
369 if ((s.st_mode & S_IFMT) == S_IFLNK) {
370 char linkto[256];
371 int len = readlink(buffer, linkto, sizeof(linkto));
372 if(len > 0) {
373 if(len > 255) {
374 linkto[252] = '.';
375 linkto[253] = '.';
376 linkto[254] = '.';
377 linkto[255] = 0;
378 } else {
379 linkto[len] = 0;
380 }
381 if (strstr(linkto, "/sdcard/") == linkto ||
382 strstr(linkto, "/system/sounds/") == linkto ||
383 strstr(linkto, "/system/media/") == linkto) {
384 result.append(" ");
385 result.append(buffer);
386 result.append(" -> ");
387 result.append(linkto);
388 result.append("\n");
389 }
390 }
391 } else {
392 result.append(" unexpected type for ");
393 result.append(buffer);
394 result.append("\n");
395 }
396 }
397 }
398 }
399 closedir(d);
400 } else {
401 result.append("couldn't open ");
402 result.append(buffer);
403 result.append("\n");
404 }
405
406#if defined(__arm__)
407 bool dumpMem = false;
408 for (size_t i = 0; i < args.size(); i++) {
409 if (args[i] == String16("-m")) {
410 dumpMem = true;
411 }
412 }
413 if (dumpMem) {
414 memStatus(fd, args);
415 }
416#endif
417 }
418 write(fd, result.string(), result.size());
419 return NO_ERROR;
420}
421
422void MediaPlayerService::removeClient(wp<Client> client)
423{
424 Mutex::Autolock lock(mLock);
425 mClients.remove(client);
426}
427
428MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t pid,
429 int32_t connId, const sp<IMediaPlayerClient>& client)
430{
431 LOGV("Client(%d) constructor", connId);
432 mPid = pid;
433 mConnId = connId;
434 mService = service;
435 mClient = client;
436 mLoop = false;
437 mStatus = NO_INIT;
438#if CALLBACK_ANTAGONIZER
439 LOGD("create Antagonizer");
440 mAntagonizer = new Antagonizer(notify, this);
441#endif
442}
443
444MediaPlayerService::Client::~Client()
445{
446 LOGV("Client(%d) destructor pid = %d", mConnId, mPid);
447 mAudioOutput.clear();
448 wp<Client> client(this);
449 disconnect();
450 mService->removeClient(client);
451}
452
453void MediaPlayerService::Client::disconnect()
454{
455 LOGV("disconnect(%d) from pid %d", mConnId, mPid);
456 // grab local reference and clear main reference to prevent future
457 // access to object
458 sp<MediaPlayerBase> p;
459 {
460 Mutex::Autolock l(mLock);
461 p = mPlayer;
462 }
463 mPlayer.clear();
464
465 // clear the notification to prevent callbacks to dead client
466 // and reset the player. We assume the player will serialize
467 // access to itself if necessary.
468 if (p != 0) {
469 p->setNotifyCallback(0, 0);
470#if CALLBACK_ANTAGONIZER
471 LOGD("kill Antagonizer");
472 mAntagonizer->kill();
473#endif
474 p->reset();
475 }
476
477 IPCThreadState::self()->flushCommands();
478}
479
480static player_type getPlayerType(int fd, int64_t offset, int64_t length)
481{
482 char buf[20];
483 lseek(fd, offset, SEEK_SET);
484 read(fd, buf, sizeof(buf));
485 lseek(fd, offset, SEEK_SET);
486
487 long ident = *((long*)buf);
488
489 // Ogg vorbis?
490 if (ident == 0x5367674f) // 'OggS'
491 return VORBIS_PLAYER;
492
493 // Some kind of MIDI?
494 EAS_DATA_HANDLE easdata;
495 if (EAS_Init(&easdata) == EAS_SUCCESS) {
496 EAS_FILE locator;
497 locator.path = NULL;
498 locator.fd = fd;
499 locator.offset = offset;
500 locator.length = length;
501 EAS_HANDLE eashandle;
502 if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
503 EAS_CloseFile(easdata, eashandle);
504 EAS_Shutdown(easdata);
505 return SONIVOX_PLAYER;
506 }
507 EAS_Shutdown(easdata);
508 }
509
510 // Fall through to PV
511 return PV_PLAYER;
512}
513
514static player_type getPlayerType(const char* url)
515{
516
517 // use MidiFile for MIDI extensions
518 int lenURL = strlen(url);
519 for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
520 int len = strlen(FILE_EXTS[i].extension);
521 int start = lenURL - len;
522 if (start > 0) {
523 if (!strncmp(url + start, FILE_EXTS[i].extension, len)) {
524 return FILE_EXTS[i].playertype;
525 }
526 }
527 }
528
529 // Fall through to PV
530 return PV_PLAYER;
531}
532
533static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
534 notify_callback_f notifyFunc)
535{
536 sp<MediaPlayerBase> p;
537 switch (playerType) {
Jean-Baptiste Queru6c5b2102009-03-21 11:40:18 -0700538#ifndef NO_OPENCORE
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800539 case PV_PLAYER:
540 LOGV(" create PVPlayer");
541 p = new PVPlayer();
542 break;
Jean-Baptiste Queru6c5b2102009-03-21 11:40:18 -0700543#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800544 case SONIVOX_PLAYER:
545 LOGV(" create MidiFile");
546 p = new MidiFile();
547 break;
548 case VORBIS_PLAYER:
549 LOGV(" create VorbisPlayer");
550 p = new VorbisPlayer();
551 break;
552 }
553 if (p != NULL) {
554 if (p->initCheck() == NO_ERROR) {
555 p->setNotifyCallback(cookie, notifyFunc);
556 } else {
557 p.clear();
558 }
559 }
560 if (p == NULL) {
561 LOGE("Failed to create player object");
562 }
563 return p;
564}
565
566sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
567{
568 // determine if we have the right player type
569 sp<MediaPlayerBase> p = mPlayer;
570 if ((p != NULL) && (p->playerType() != playerType)) {
571 LOGV("delete player");
572 p.clear();
573 }
574 if (p == NULL) {
575 p = android::createPlayer(playerType, this, notify);
576 }
577 return p;
578}
579
580status_t MediaPlayerService::Client::setDataSource(const char *url)
581{
582 LOGV("setDataSource(%s)", url);
583 if (url == NULL)
584 return UNKNOWN_ERROR;
585
586 if (strncmp(url, "content://", 10) == 0) {
587 // get a filedescriptor for the content Uri and
588 // pass it to the setDataSource(fd) method
589
590 String16 url16(url);
591 int fd = android::openContentProviderFile(url16);
592 if (fd < 0)
593 {
594 LOGE("Couldn't open fd for %s", url);
595 return UNKNOWN_ERROR;
596 }
597 setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
598 close(fd);
599 return mStatus;
600 } else {
601 player_type playerType = getPlayerType(url);
602 LOGV("player type = %d", playerType);
603
604 // create the right type of player
605 sp<MediaPlayerBase> p = createPlayer(playerType);
606 if (p == NULL) return NO_INIT;
607
608 if (!p->hardwareOutput()) {
609 mAudioOutput = new AudioOutput();
610 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
611 }
612
613 // now set data source
614 LOGV(" setDataSource");
615 mStatus = p->setDataSource(url);
616 if (mStatus == NO_ERROR) mPlayer = p;
617 return mStatus;
618 }
619}
620
621status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
622{
623 LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
624 struct stat sb;
625 int ret = fstat(fd, &sb);
626 if (ret != 0) {
627 LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
628 return UNKNOWN_ERROR;
629 }
630
631 LOGV("st_dev = %llu", sb.st_dev);
632 LOGV("st_mode = %u", sb.st_mode);
633 LOGV("st_uid = %lu", sb.st_uid);
634 LOGV("st_gid = %lu", sb.st_gid);
635 LOGV("st_size = %llu", sb.st_size);
636
637 if (offset >= sb.st_size) {
638 LOGE("offset error");
639 ::close(fd);
640 return UNKNOWN_ERROR;
641 }
642 if (offset + length > sb.st_size) {
643 length = sb.st_size - offset;
644 LOGV("calculated length = %lld", length);
645 }
646
647 player_type playerType = getPlayerType(fd, offset, length);
648 LOGV("player type = %d", playerType);
649
650 // create the right type of player
651 sp<MediaPlayerBase> p = createPlayer(playerType);
652 if (p == NULL) return NO_INIT;
653
654 if (!p->hardwareOutput()) {
655 mAudioOutput = new AudioOutput();
656 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
657 }
658
659 // now set data source
660 mStatus = p->setDataSource(fd, offset, length);
661 if (mStatus == NO_ERROR) mPlayer = p;
662 return mStatus;
663}
664
665status_t MediaPlayerService::Client::setVideoSurface(const sp<ISurface>& surface)
666{
667 LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());
668 sp<MediaPlayerBase> p = getPlayer();
669 if (p == 0) return UNKNOWN_ERROR;
670 return p->setVideoSurface(surface);
671}
672
673status_t MediaPlayerService::Client::prepareAsync()
674{
675 LOGV("[%d] prepareAsync", mConnId);
676 sp<MediaPlayerBase> p = getPlayer();
677 if (p == 0) return UNKNOWN_ERROR;
678 status_t ret = p->prepareAsync();
679#if CALLBACK_ANTAGONIZER
680 LOGD("start Antagonizer");
681 if (ret == NO_ERROR) mAntagonizer->start();
682#endif
683 return ret;
684}
685
686status_t MediaPlayerService::Client::start()
687{
688 LOGV("[%d] start", mConnId);
689 sp<MediaPlayerBase> p = getPlayer();
690 if (p == 0) return UNKNOWN_ERROR;
691 p->setLooping(mLoop);
692 return p->start();
693}
694
695status_t MediaPlayerService::Client::stop()
696{
697 LOGV("[%d] stop", mConnId);
698 sp<MediaPlayerBase> p = getPlayer();
699 if (p == 0) return UNKNOWN_ERROR;
700 return p->stop();
701}
702
703status_t MediaPlayerService::Client::pause()
704{
705 LOGV("[%d] pause", mConnId);
706 sp<MediaPlayerBase> p = getPlayer();
707 if (p == 0) return UNKNOWN_ERROR;
708 return p->pause();
709}
710
711status_t MediaPlayerService::Client::isPlaying(bool* state)
712{
713 *state = false;
714 sp<MediaPlayerBase> p = getPlayer();
715 if (p == 0) return UNKNOWN_ERROR;
716 *state = p->isPlaying();
717 LOGV("[%d] isPlaying: %d", mConnId, *state);
718 return NO_ERROR;
719}
720
721status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
722{
723 LOGV("getCurrentPosition");
724 sp<MediaPlayerBase> p = getPlayer();
725 if (p == 0) return UNKNOWN_ERROR;
726 status_t ret = p->getCurrentPosition(msec);
727 if (ret == NO_ERROR) {
728 LOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
729 } else {
730 LOGE("getCurrentPosition returned %d", ret);
731 }
732 return ret;
733}
734
735status_t MediaPlayerService::Client::getDuration(int *msec)
736{
737 LOGV("getDuration");
738 sp<MediaPlayerBase> p = getPlayer();
739 if (p == 0) return UNKNOWN_ERROR;
740 status_t ret = p->getDuration(msec);
741 if (ret == NO_ERROR) {
742 LOGV("[%d] getDuration = %d", mConnId, *msec);
743 } else {
744 LOGE("getDuration returned %d", ret);
745 }
746 return ret;
747}
748
749status_t MediaPlayerService::Client::seekTo(int msec)
750{
751 LOGV("[%d] seekTo(%d)", mConnId, msec);
752 sp<MediaPlayerBase> p = getPlayer();
753 if (p == 0) return UNKNOWN_ERROR;
754 return p->seekTo(msec);
755}
756
757status_t MediaPlayerService::Client::reset()
758{
759 LOGV("[%d] reset", mConnId);
760 sp<MediaPlayerBase> p = getPlayer();
761 if (p == 0) return UNKNOWN_ERROR;
762 return p->reset();
763}
764
765status_t MediaPlayerService::Client::setAudioStreamType(int type)
766{
767 LOGV("[%d] setAudioStreamType(%d)", mConnId, type);
768 // TODO: for hardware output, call player instead
769 Mutex::Autolock l(mLock);
770 if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
771 return NO_ERROR;
772}
773
774status_t MediaPlayerService::Client::setLooping(int loop)
775{
776 LOGV("[%d] setLooping(%d)", mConnId, loop);
777 mLoop = loop;
778 sp<MediaPlayerBase> p = getPlayer();
779 if (p != 0) return p->setLooping(loop);
780 return NO_ERROR;
781}
782
783status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
784{
785 LOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
786 // TODO: for hardware output, call player instead
787 Mutex::Autolock l(mLock);
788 if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
789 return NO_ERROR;
790}
791
792void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
793{
794 Client* client = static_cast<Client*>(cookie);
795 LOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
796 client->mClient->notify(msg, ext1, ext2);
797}
798
799#if CALLBACK_ANTAGONIZER
800const int Antagonizer::interval = 10000; // 10 msecs
801
802Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
803 mExit(false), mActive(false), mClient(client), mCb(cb)
804{
805 createThread(callbackThread, this);
806}
807
808void Antagonizer::kill()
809{
810 Mutex::Autolock _l(mLock);
811 mActive = false;
812 mExit = true;
813 mCondition.wait(mLock);
814}
815
816int Antagonizer::callbackThread(void* user)
817{
818 LOGD("Antagonizer started");
819 Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
820 while (!p->mExit) {
821 if (p->mActive) {
822 LOGV("send event");
823 p->mCb(p->mClient, 0, 0, 0);
824 }
825 usleep(interval);
826 }
827 Mutex::Autolock _l(p->mLock);
828 p->mCondition.signal();
829 LOGD("Antagonizer stopped");
830 return 0;
831}
832#endif
833
834static size_t kDefaultHeapSize = 1024 * 1024; // 1MB
835
836sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
837{
838 LOGV("decode(%s)", url);
839 sp<MemoryBase> mem;
840 sp<MediaPlayerBase> player;
841
842 // Protect our precious, precious DRMd ringtones by only allowing
843 // decoding of http, but not filesystem paths or content Uris.
844 // If the application wants to decode those, it should open a
845 // filedescriptor for them and use that.
846 if (url != NULL && strncmp(url, "http://", 7) != 0) {
847 LOGD("Can't decode %s by path, use filedescriptor instead", url);
848 return mem;
849 }
850
851 player_type playerType = getPlayerType(url);
852 LOGV("player type = %d", playerType);
853
854 // create the right type of player
855 sp<AudioCache> cache = new AudioCache(url);
856 player = android::createPlayer(playerType, cache.get(), cache->notify);
857 if (player == NULL) goto Exit;
858 if (player->hardwareOutput()) goto Exit;
859
860 static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
861
862 // set data source
863 if (player->setDataSource(url) != NO_ERROR) goto Exit;
864
865 LOGV("prepare");
866 player->prepareAsync();
867
868 LOGV("wait for prepare");
869 if (cache->wait() != NO_ERROR) goto Exit;
870
871 LOGV("start");
872 player->start();
873
874 LOGV("wait for playback complete");
875 if (cache->wait() != NO_ERROR) goto Exit;
876
877 mem = new MemoryBase(cache->getHeap(), 0, cache->size());
878 *pSampleRate = cache->sampleRate();
879 *pNumChannels = cache->channelCount();
880 *pFormat = cache->format();
881 LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
882
883Exit:
884 if (player != 0) player->reset();
885 return mem;
886}
887
888sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
889{
890 LOGV("decode(%d, %lld, %lld)", fd, offset, length);
891 sp<MemoryBase> mem;
892 sp<MediaPlayerBase> player;
893
894 player_type playerType = getPlayerType(fd, offset, length);
895 LOGV("player type = %d", playerType);
896
897 // create the right type of player
898 sp<AudioCache> cache = new AudioCache("decode_fd");
899 player = android::createPlayer(playerType, cache.get(), cache->notify);
900 if (player == NULL) goto Exit;
901 if (player->hardwareOutput()) goto Exit;
902
903 static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
904
905 // set data source
906 if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
907
908 LOGV("prepare");
909 player->prepareAsync();
910
911 LOGV("wait for prepare");
912 if (cache->wait() != NO_ERROR) goto Exit;
913
914 LOGV("start");
915 player->start();
916
917 LOGV("wait for playback complete");
918 if (cache->wait() != NO_ERROR) goto Exit;
919
920 mem = new MemoryBase(cache->getHeap(), 0, cache->size());
921 *pSampleRate = cache->sampleRate();
922 *pNumChannels = cache->channelCount();
923 *pFormat = cache->format();
924 LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
925
926Exit:
927 if (player != 0) player->reset();
928 ::close(fd);
929 return mem;
930}
931
932#undef LOG_TAG
933#define LOG_TAG "AudioSink"
934MediaPlayerService::AudioOutput::AudioOutput()
935{
936 mTrack = 0;
937 mStreamType = AudioSystem::MUSIC;
938 mLeftVolume = 1.0;
939 mRightVolume = 1.0;
940 mLatency = 0;
941 mMsecsPerFrame = 0;
942 setMinBufferCount();
943}
944
945MediaPlayerService::AudioOutput::~AudioOutput()
946{
947 close();
948}
949
950void MediaPlayerService::AudioOutput::setMinBufferCount()
951{
952 char value[PROPERTY_VALUE_MAX];
953 if (property_get("ro.kernel.qemu", value, 0)) {
954 mIsOnEmulator = true;
955 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
956 }
957}
958
959bool MediaPlayerService::AudioOutput::isOnEmulator()
960{
961 setMinBufferCount();
962 return mIsOnEmulator;
963}
964
965int MediaPlayerService::AudioOutput::getMinBufferCount()
966{
967 setMinBufferCount();
968 return mMinBufferCount;
969}
970
971ssize_t MediaPlayerService::AudioOutput::bufferSize() const
972{
973 if (mTrack == 0) return NO_INIT;
974 return mTrack->frameCount() * frameSize();
975}
976
977ssize_t MediaPlayerService::AudioOutput::frameCount() const
978{
979 if (mTrack == 0) return NO_INIT;
980 return mTrack->frameCount();
981}
982
983ssize_t MediaPlayerService::AudioOutput::channelCount() const
984{
985 if (mTrack == 0) return NO_INIT;
986 return mTrack->channelCount();
987}
988
989ssize_t MediaPlayerService::AudioOutput::frameSize() const
990{
991 if (mTrack == 0) return NO_INIT;
992 return mTrack->frameSize();
993}
994
995uint32_t MediaPlayerService::AudioOutput::latency () const
996{
997 return mLatency;
998}
999
1000float MediaPlayerService::AudioOutput::msecsPerFrame() const
1001{
1002 return mMsecsPerFrame;
1003}
1004
1005status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int format, int bufferCount)
1006{
1007 // Check argument "bufferCount" against the mininum buffer count
1008 if (bufferCount < mMinBufferCount) {
1009 LOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
1010 bufferCount = mMinBufferCount;
1011
1012 }
1013 LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
1014 if (mTrack) close();
1015 int afSampleRate;
1016 int afFrameCount;
1017 int frameCount;
1018
1019 if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
1020 return NO_INIT;
1021 }
1022 if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
1023 return NO_INIT;
1024 }
1025
1026 frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
1027 AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount);
1028 if ((t == 0) || (t->initCheck() != NO_ERROR)) {
1029 LOGE("Unable to create audio track");
1030 delete t;
1031 return NO_INIT;
1032 }
1033
1034 LOGV("setVolume");
1035 t->setVolume(mLeftVolume, mRightVolume);
1036 mMsecsPerFrame = 1.e3 / (float) sampleRate;
1037 mLatency = t->latency() + kAudioVideoDelayMs;
1038 mTrack = t;
1039 return NO_ERROR;
1040}
1041
1042void MediaPlayerService::AudioOutput::start()
1043{
1044 LOGV("start");
1045 if (mTrack) {
1046 mTrack->setVolume(mLeftVolume, mRightVolume);
1047 mTrack->start();
1048 }
1049}
1050
1051ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
1052{
1053 //LOGV("write(%p, %u)", buffer, size);
1054 if (mTrack) return mTrack->write(buffer, size);
1055 return NO_INIT;
1056}
1057
1058void MediaPlayerService::AudioOutput::stop()
1059{
1060 LOGV("stop");
1061 if (mTrack) mTrack->stop();
1062}
1063
1064void MediaPlayerService::AudioOutput::flush()
1065{
1066 LOGV("flush");
1067 if (mTrack) mTrack->flush();
1068}
1069
1070void MediaPlayerService::AudioOutput::pause()
1071{
1072 LOGV("pause");
1073 if (mTrack) mTrack->pause();
1074}
1075
1076void MediaPlayerService::AudioOutput::close()
1077{
1078 LOGV("close");
1079 delete mTrack;
1080 mTrack = 0;
1081}
1082
1083void MediaPlayerService::AudioOutput::setVolume(float left, float right)
1084{
1085 LOGV("setVolume(%f, %f)", left, right);
1086 mLeftVolume = left;
1087 mRightVolume = right;
1088 if (mTrack) {
1089 mTrack->setVolume(left, right);
1090 }
1091}
1092
1093#undef LOG_TAG
1094#define LOG_TAG "AudioCache"
1095MediaPlayerService::AudioCache::AudioCache(const char* name) :
1096 mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
1097 mError(NO_ERROR), mCommandComplete(false)
1098{
1099 // create ashmem heap
1100 mHeap = new MemoryHeapBase(kDefaultHeapSize, 0, name);
1101}
1102
1103uint32_t MediaPlayerService::AudioCache::latency () const
1104{
1105 return 0;
1106}
1107
1108float MediaPlayerService::AudioCache::msecsPerFrame() const
1109{
1110 return mMsecsPerFrame;
1111}
1112
1113status_t MediaPlayerService::AudioCache::open(uint32_t sampleRate, int channelCount, int format, int bufferCount)
1114{
1115 LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
1116 if (mHeap->getHeapID() < 0) return NO_INIT;
1117 mSampleRate = sampleRate;
1118 mChannelCount = (uint16_t)channelCount;
1119 mFormat = (uint16_t)format;
1120 mMsecsPerFrame = 1.e3 / (float) sampleRate;
1121 return NO_ERROR;
1122}
1123
1124ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
1125{
1126 LOGV("write(%p, %u)", buffer, size);
1127 if ((buffer == 0) || (size == 0)) return size;
1128
1129 uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
1130 if (p == NULL) return NO_INIT;
1131 p += mSize;
1132 LOGV("memcpy(%p, %p, %u)", p, buffer, size);
1133 if (mSize + size > mHeap->getSize()) {
1134 LOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
1135 size = mHeap->getSize() - mSize;
1136 }
1137 memcpy(p, buffer, size);
1138 mSize += size;
1139 return size;
1140}
1141
1142// call with lock held
1143status_t MediaPlayerService::AudioCache::wait()
1144{
1145 Mutex::Autolock lock(mLock);
1146 if (!mCommandComplete) {
1147 mSignal.wait(mLock);
1148 }
1149 mCommandComplete = false;
1150
1151 if (mError == NO_ERROR) {
1152 LOGV("wait - success");
1153 } else {
1154 LOGV("wait - error");
1155 }
1156 return mError;
1157}
1158
1159void MediaPlayerService::AudioCache::notify(void* cookie, int msg, int ext1, int ext2)
1160{
1161 LOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
1162 AudioCache* p = static_cast<AudioCache*>(cookie);
1163
1164 // ignore buffering messages
1165 if (msg == MEDIA_BUFFERING_UPDATE) return;
1166
1167 // set error condition
1168 if (msg == MEDIA_ERROR) {
1169 LOGE("Error %d, %d occurred", ext1, ext2);
1170 p->mError = ext1;
1171 }
1172
1173 // wake up thread
1174 LOGV("wakeup thread");
1175 p->mCommandComplete = true;
1176 p->mSignal.signal();
1177}
1178
1179}; // namespace android