blob: 8ef0dc6c42c43735d7778874f4b8cfcbc502e79b [file] [log] [blame]
The Android Open Source Project9066cfe2009-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 Queru680f8c72009-03-21 11:40:18 -0700108#ifndef NO_OPENCORE
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 sp<MediaRecorderClient> recorder = new MediaRecorderClient(pid);
Jean-Baptiste Queru680f8c72009-03-21 11:40:18 -0700110#else
111 sp<MediaRecorderClient> recorder = NULL;
112#endif
The Android Open Source Project9066cfe2009-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 }
Dave Sparkscb9a44e2009-03-24 17:57:12 -0700463 mClient.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 mPlayer.clear();
465
466 // clear the notification to prevent callbacks to dead client
467 // and reset the player. We assume the player will serialize
468 // access to itself if necessary.
469 if (p != 0) {
470 p->setNotifyCallback(0, 0);
471#if CALLBACK_ANTAGONIZER
472 LOGD("kill Antagonizer");
473 mAntagonizer->kill();
474#endif
475 p->reset();
476 }
477
478 IPCThreadState::self()->flushCommands();
479}
480
481static player_type getPlayerType(int fd, int64_t offset, int64_t length)
482{
483 char buf[20];
484 lseek(fd, offset, SEEK_SET);
485 read(fd, buf, sizeof(buf));
486 lseek(fd, offset, SEEK_SET);
487
488 long ident = *((long*)buf);
489
490 // Ogg vorbis?
491 if (ident == 0x5367674f) // 'OggS'
492 return VORBIS_PLAYER;
493
494 // Some kind of MIDI?
495 EAS_DATA_HANDLE easdata;
496 if (EAS_Init(&easdata) == EAS_SUCCESS) {
497 EAS_FILE locator;
498 locator.path = NULL;
499 locator.fd = fd;
500 locator.offset = offset;
501 locator.length = length;
502 EAS_HANDLE eashandle;
503 if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
504 EAS_CloseFile(easdata, eashandle);
505 EAS_Shutdown(easdata);
506 return SONIVOX_PLAYER;
507 }
508 EAS_Shutdown(easdata);
509 }
510
511 // Fall through to PV
512 return PV_PLAYER;
513}
514
515static player_type getPlayerType(const char* url)
516{
517
518 // use MidiFile for MIDI extensions
519 int lenURL = strlen(url);
520 for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
521 int len = strlen(FILE_EXTS[i].extension);
522 int start = lenURL - len;
523 if (start > 0) {
524 if (!strncmp(url + start, FILE_EXTS[i].extension, len)) {
525 return FILE_EXTS[i].playertype;
526 }
527 }
528 }
529
530 // Fall through to PV
531 return PV_PLAYER;
532}
533
534static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
535 notify_callback_f notifyFunc)
536{
537 sp<MediaPlayerBase> p;
538 switch (playerType) {
Jean-Baptiste Queru680f8c72009-03-21 11:40:18 -0700539#ifndef NO_OPENCORE
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 case PV_PLAYER:
541 LOGV(" create PVPlayer");
542 p = new PVPlayer();
543 break;
Jean-Baptiste Queru680f8c72009-03-21 11:40:18 -0700544#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 case SONIVOX_PLAYER:
546 LOGV(" create MidiFile");
547 p = new MidiFile();
548 break;
549 case VORBIS_PLAYER:
550 LOGV(" create VorbisPlayer");
551 p = new VorbisPlayer();
552 break;
553 }
554 if (p != NULL) {
555 if (p->initCheck() == NO_ERROR) {
556 p->setNotifyCallback(cookie, notifyFunc);
557 } else {
558 p.clear();
559 }
560 }
561 if (p == NULL) {
562 LOGE("Failed to create player object");
563 }
564 return p;
565}
566
567sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
568{
569 // determine if we have the right player type
570 sp<MediaPlayerBase> p = mPlayer;
571 if ((p != NULL) && (p->playerType() != playerType)) {
572 LOGV("delete player");
573 p.clear();
574 }
575 if (p == NULL) {
576 p = android::createPlayer(playerType, this, notify);
577 }
578 return p;
579}
580
581status_t MediaPlayerService::Client::setDataSource(const char *url)
582{
583 LOGV("setDataSource(%s)", url);
584 if (url == NULL)
585 return UNKNOWN_ERROR;
586
587 if (strncmp(url, "content://", 10) == 0) {
588 // get a filedescriptor for the content Uri and
589 // pass it to the setDataSource(fd) method
590
591 String16 url16(url);
592 int fd = android::openContentProviderFile(url16);
593 if (fd < 0)
594 {
595 LOGE("Couldn't open fd for %s", url);
596 return UNKNOWN_ERROR;
597 }
598 setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
599 close(fd);
600 return mStatus;
601 } else {
602 player_type playerType = getPlayerType(url);
603 LOGV("player type = %d", playerType);
604
605 // create the right type of player
606 sp<MediaPlayerBase> p = createPlayer(playerType);
607 if (p == NULL) return NO_INIT;
608
609 if (!p->hardwareOutput()) {
610 mAudioOutput = new AudioOutput();
611 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
612 }
613
614 // now set data source
615 LOGV(" setDataSource");
616 mStatus = p->setDataSource(url);
617 if (mStatus == NO_ERROR) mPlayer = p;
618 return mStatus;
619 }
620}
621
622status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
623{
624 LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
625 struct stat sb;
626 int ret = fstat(fd, &sb);
627 if (ret != 0) {
628 LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
629 return UNKNOWN_ERROR;
630 }
631
632 LOGV("st_dev = %llu", sb.st_dev);
633 LOGV("st_mode = %u", sb.st_mode);
634 LOGV("st_uid = %lu", sb.st_uid);
635 LOGV("st_gid = %lu", sb.st_gid);
636 LOGV("st_size = %llu", sb.st_size);
637
638 if (offset >= sb.st_size) {
639 LOGE("offset error");
640 ::close(fd);
641 return UNKNOWN_ERROR;
642 }
643 if (offset + length > sb.st_size) {
644 length = sb.st_size - offset;
645 LOGV("calculated length = %lld", length);
646 }
647
648 player_type playerType = getPlayerType(fd, offset, length);
649 LOGV("player type = %d", playerType);
650
651 // create the right type of player
652 sp<MediaPlayerBase> p = createPlayer(playerType);
653 if (p == NULL) return NO_INIT;
654
655 if (!p->hardwareOutput()) {
656 mAudioOutput = new AudioOutput();
657 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
658 }
659
660 // now set data source
661 mStatus = p->setDataSource(fd, offset, length);
662 if (mStatus == NO_ERROR) mPlayer = p;
663 return mStatus;
664}
665
666status_t MediaPlayerService::Client::setVideoSurface(const sp<ISurface>& surface)
667{
668 LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());
669 sp<MediaPlayerBase> p = getPlayer();
670 if (p == 0) return UNKNOWN_ERROR;
671 return p->setVideoSurface(surface);
672}
673
674status_t MediaPlayerService::Client::prepareAsync()
675{
676 LOGV("[%d] prepareAsync", mConnId);
677 sp<MediaPlayerBase> p = getPlayer();
678 if (p == 0) return UNKNOWN_ERROR;
679 status_t ret = p->prepareAsync();
680#if CALLBACK_ANTAGONIZER
681 LOGD("start Antagonizer");
682 if (ret == NO_ERROR) mAntagonizer->start();
683#endif
684 return ret;
685}
686
687status_t MediaPlayerService::Client::start()
688{
689 LOGV("[%d] start", mConnId);
690 sp<MediaPlayerBase> p = getPlayer();
691 if (p == 0) return UNKNOWN_ERROR;
692 p->setLooping(mLoop);
693 return p->start();
694}
695
696status_t MediaPlayerService::Client::stop()
697{
698 LOGV("[%d] stop", mConnId);
699 sp<MediaPlayerBase> p = getPlayer();
700 if (p == 0) return UNKNOWN_ERROR;
701 return p->stop();
702}
703
704status_t MediaPlayerService::Client::pause()
705{
706 LOGV("[%d] pause", mConnId);
707 sp<MediaPlayerBase> p = getPlayer();
708 if (p == 0) return UNKNOWN_ERROR;
709 return p->pause();
710}
711
712status_t MediaPlayerService::Client::isPlaying(bool* state)
713{
714 *state = false;
715 sp<MediaPlayerBase> p = getPlayer();
716 if (p == 0) return UNKNOWN_ERROR;
717 *state = p->isPlaying();
718 LOGV("[%d] isPlaying: %d", mConnId, *state);
719 return NO_ERROR;
720}
721
722status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
723{
724 LOGV("getCurrentPosition");
725 sp<MediaPlayerBase> p = getPlayer();
726 if (p == 0) return UNKNOWN_ERROR;
727 status_t ret = p->getCurrentPosition(msec);
728 if (ret == NO_ERROR) {
729 LOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
730 } else {
731 LOGE("getCurrentPosition returned %d", ret);
732 }
733 return ret;
734}
735
736status_t MediaPlayerService::Client::getDuration(int *msec)
737{
738 LOGV("getDuration");
739 sp<MediaPlayerBase> p = getPlayer();
740 if (p == 0) return UNKNOWN_ERROR;
741 status_t ret = p->getDuration(msec);
742 if (ret == NO_ERROR) {
743 LOGV("[%d] getDuration = %d", mConnId, *msec);
744 } else {
745 LOGE("getDuration returned %d", ret);
746 }
747 return ret;
748}
749
750status_t MediaPlayerService::Client::seekTo(int msec)
751{
752 LOGV("[%d] seekTo(%d)", mConnId, msec);
753 sp<MediaPlayerBase> p = getPlayer();
754 if (p == 0) return UNKNOWN_ERROR;
755 return p->seekTo(msec);
756}
757
758status_t MediaPlayerService::Client::reset()
759{
760 LOGV("[%d] reset", mConnId);
761 sp<MediaPlayerBase> p = getPlayer();
762 if (p == 0) return UNKNOWN_ERROR;
763 return p->reset();
764}
765
766status_t MediaPlayerService::Client::setAudioStreamType(int type)
767{
768 LOGV("[%d] setAudioStreamType(%d)", mConnId, type);
769 // TODO: for hardware output, call player instead
770 Mutex::Autolock l(mLock);
771 if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
772 return NO_ERROR;
773}
774
775status_t MediaPlayerService::Client::setLooping(int loop)
776{
777 LOGV("[%d] setLooping(%d)", mConnId, loop);
778 mLoop = loop;
779 sp<MediaPlayerBase> p = getPlayer();
780 if (p != 0) return p->setLooping(loop);
781 return NO_ERROR;
782}
783
784status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
785{
786 LOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
787 // TODO: for hardware output, call player instead
788 Mutex::Autolock l(mLock);
789 if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
790 return NO_ERROR;
791}
792
793void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
794{
795 Client* client = static_cast<Client*>(cookie);
796 LOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
797 client->mClient->notify(msg, ext1, ext2);
798}
799
800#if CALLBACK_ANTAGONIZER
801const int Antagonizer::interval = 10000; // 10 msecs
802
803Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
804 mExit(false), mActive(false), mClient(client), mCb(cb)
805{
806 createThread(callbackThread, this);
807}
808
809void Antagonizer::kill()
810{
811 Mutex::Autolock _l(mLock);
812 mActive = false;
813 mExit = true;
814 mCondition.wait(mLock);
815}
816
817int Antagonizer::callbackThread(void* user)
818{
819 LOGD("Antagonizer started");
820 Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
821 while (!p->mExit) {
822 if (p->mActive) {
823 LOGV("send event");
824 p->mCb(p->mClient, 0, 0, 0);
825 }
826 usleep(interval);
827 }
828 Mutex::Autolock _l(p->mLock);
829 p->mCondition.signal();
830 LOGD("Antagonizer stopped");
831 return 0;
832}
833#endif
834
835static size_t kDefaultHeapSize = 1024 * 1024; // 1MB
836
837sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
838{
839 LOGV("decode(%s)", url);
840 sp<MemoryBase> mem;
841 sp<MediaPlayerBase> player;
842
843 // Protect our precious, precious DRMd ringtones by only allowing
844 // decoding of http, but not filesystem paths or content Uris.
845 // If the application wants to decode those, it should open a
846 // filedescriptor for them and use that.
847 if (url != NULL && strncmp(url, "http://", 7) != 0) {
848 LOGD("Can't decode %s by path, use filedescriptor instead", url);
849 return mem;
850 }
851
852 player_type playerType = getPlayerType(url);
853 LOGV("player type = %d", playerType);
854
855 // create the right type of player
856 sp<AudioCache> cache = new AudioCache(url);
857 player = android::createPlayer(playerType, cache.get(), cache->notify);
858 if (player == NULL) goto Exit;
859 if (player->hardwareOutput()) goto Exit;
860
861 static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
862
863 // set data source
864 if (player->setDataSource(url) != NO_ERROR) goto Exit;
865
866 LOGV("prepare");
867 player->prepareAsync();
868
869 LOGV("wait for prepare");
870 if (cache->wait() != NO_ERROR) goto Exit;
871
872 LOGV("start");
873 player->start();
874
875 LOGV("wait for playback complete");
876 if (cache->wait() != NO_ERROR) goto Exit;
877
878 mem = new MemoryBase(cache->getHeap(), 0, cache->size());
879 *pSampleRate = cache->sampleRate();
880 *pNumChannels = cache->channelCount();
881 *pFormat = cache->format();
882 LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
883
884Exit:
885 if (player != 0) player->reset();
886 return mem;
887}
888
889sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
890{
891 LOGV("decode(%d, %lld, %lld)", fd, offset, length);
892 sp<MemoryBase> mem;
893 sp<MediaPlayerBase> player;
894
895 player_type playerType = getPlayerType(fd, offset, length);
896 LOGV("player type = %d", playerType);
897
898 // create the right type of player
899 sp<AudioCache> cache = new AudioCache("decode_fd");
900 player = android::createPlayer(playerType, cache.get(), cache->notify);
901 if (player == NULL) goto Exit;
902 if (player->hardwareOutput()) goto Exit;
903
904 static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
905
906 // set data source
907 if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
908
909 LOGV("prepare");
910 player->prepareAsync();
911
912 LOGV("wait for prepare");
913 if (cache->wait() != NO_ERROR) goto Exit;
914
915 LOGV("start");
916 player->start();
917
918 LOGV("wait for playback complete");
919 if (cache->wait() != NO_ERROR) goto Exit;
920
921 mem = new MemoryBase(cache->getHeap(), 0, cache->size());
922 *pSampleRate = cache->sampleRate();
923 *pNumChannels = cache->channelCount();
924 *pFormat = cache->format();
925 LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
926
927Exit:
928 if (player != 0) player->reset();
929 ::close(fd);
930 return mem;
931}
932
933#undef LOG_TAG
934#define LOG_TAG "AudioSink"
935MediaPlayerService::AudioOutput::AudioOutput()
936{
937 mTrack = 0;
938 mStreamType = AudioSystem::MUSIC;
939 mLeftVolume = 1.0;
940 mRightVolume = 1.0;
941 mLatency = 0;
942 mMsecsPerFrame = 0;
943 setMinBufferCount();
944}
945
946MediaPlayerService::AudioOutput::~AudioOutput()
947{
948 close();
949}
950
951void MediaPlayerService::AudioOutput::setMinBufferCount()
952{
953 char value[PROPERTY_VALUE_MAX];
954 if (property_get("ro.kernel.qemu", value, 0)) {
955 mIsOnEmulator = true;
956 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
957 }
958}
959
960bool MediaPlayerService::AudioOutput::isOnEmulator()
961{
962 setMinBufferCount();
963 return mIsOnEmulator;
964}
965
966int MediaPlayerService::AudioOutput::getMinBufferCount()
967{
968 setMinBufferCount();
969 return mMinBufferCount;
970}
971
972ssize_t MediaPlayerService::AudioOutput::bufferSize() const
973{
974 if (mTrack == 0) return NO_INIT;
975 return mTrack->frameCount() * frameSize();
976}
977
978ssize_t MediaPlayerService::AudioOutput::frameCount() const
979{
980 if (mTrack == 0) return NO_INIT;
981 return mTrack->frameCount();
982}
983
984ssize_t MediaPlayerService::AudioOutput::channelCount() const
985{
986 if (mTrack == 0) return NO_INIT;
987 return mTrack->channelCount();
988}
989
990ssize_t MediaPlayerService::AudioOutput::frameSize() const
991{
992 if (mTrack == 0) return NO_INIT;
993 return mTrack->frameSize();
994}
995
996uint32_t MediaPlayerService::AudioOutput::latency () const
997{
998 return mLatency;
999}
1000
1001float MediaPlayerService::AudioOutput::msecsPerFrame() const
1002{
1003 return mMsecsPerFrame;
1004}
1005
1006status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int format, int bufferCount)
1007{
1008 // Check argument "bufferCount" against the mininum buffer count
1009 if (bufferCount < mMinBufferCount) {
1010 LOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
1011 bufferCount = mMinBufferCount;
1012
1013 }
1014 LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
1015 if (mTrack) close();
1016 int afSampleRate;
1017 int afFrameCount;
1018 int frameCount;
1019
1020 if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
1021 return NO_INIT;
1022 }
1023 if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
1024 return NO_INIT;
1025 }
1026
1027 frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
1028 AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount);
1029 if ((t == 0) || (t->initCheck() != NO_ERROR)) {
1030 LOGE("Unable to create audio track");
1031 delete t;
1032 return NO_INIT;
1033 }
1034
1035 LOGV("setVolume");
1036 t->setVolume(mLeftVolume, mRightVolume);
1037 mMsecsPerFrame = 1.e3 / (float) sampleRate;
1038 mLatency = t->latency() + kAudioVideoDelayMs;
1039 mTrack = t;
1040 return NO_ERROR;
1041}
1042
1043void MediaPlayerService::AudioOutput::start()
1044{
1045 LOGV("start");
1046 if (mTrack) {
1047 mTrack->setVolume(mLeftVolume, mRightVolume);
1048 mTrack->start();
1049 }
1050}
1051
1052ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
1053{
1054 //LOGV("write(%p, %u)", buffer, size);
1055 if (mTrack) return mTrack->write(buffer, size);
1056 return NO_INIT;
1057}
1058
1059void MediaPlayerService::AudioOutput::stop()
1060{
1061 LOGV("stop");
1062 if (mTrack) mTrack->stop();
1063}
1064
1065void MediaPlayerService::AudioOutput::flush()
1066{
1067 LOGV("flush");
1068 if (mTrack) mTrack->flush();
1069}
1070
1071void MediaPlayerService::AudioOutput::pause()
1072{
1073 LOGV("pause");
1074 if (mTrack) mTrack->pause();
1075}
1076
1077void MediaPlayerService::AudioOutput::close()
1078{
1079 LOGV("close");
1080 delete mTrack;
1081 mTrack = 0;
1082}
1083
1084void MediaPlayerService::AudioOutput::setVolume(float left, float right)
1085{
1086 LOGV("setVolume(%f, %f)", left, right);
1087 mLeftVolume = left;
1088 mRightVolume = right;
1089 if (mTrack) {
1090 mTrack->setVolume(left, right);
1091 }
1092}
1093
1094#undef LOG_TAG
1095#define LOG_TAG "AudioCache"
1096MediaPlayerService::AudioCache::AudioCache(const char* name) :
1097 mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
1098 mError(NO_ERROR), mCommandComplete(false)
1099{
1100 // create ashmem heap
1101 mHeap = new MemoryHeapBase(kDefaultHeapSize, 0, name);
1102}
1103
1104uint32_t MediaPlayerService::AudioCache::latency () const
1105{
1106 return 0;
1107}
1108
1109float MediaPlayerService::AudioCache::msecsPerFrame() const
1110{
1111 return mMsecsPerFrame;
1112}
1113
1114status_t MediaPlayerService::AudioCache::open(uint32_t sampleRate, int channelCount, int format, int bufferCount)
1115{
1116 LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
1117 if (mHeap->getHeapID() < 0) return NO_INIT;
1118 mSampleRate = sampleRate;
1119 mChannelCount = (uint16_t)channelCount;
1120 mFormat = (uint16_t)format;
1121 mMsecsPerFrame = 1.e3 / (float) sampleRate;
1122 return NO_ERROR;
1123}
1124
1125ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
1126{
1127 LOGV("write(%p, %u)", buffer, size);
1128 if ((buffer == 0) || (size == 0)) return size;
1129
1130 uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
1131 if (p == NULL) return NO_INIT;
1132 p += mSize;
1133 LOGV("memcpy(%p, %p, %u)", p, buffer, size);
1134 if (mSize + size > mHeap->getSize()) {
1135 LOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
1136 size = mHeap->getSize() - mSize;
1137 }
1138 memcpy(p, buffer, size);
1139 mSize += size;
1140 return size;
1141}
1142
1143// call with lock held
1144status_t MediaPlayerService::AudioCache::wait()
1145{
1146 Mutex::Autolock lock(mLock);
1147 if (!mCommandComplete) {
1148 mSignal.wait(mLock);
1149 }
1150 mCommandComplete = false;
1151
1152 if (mError == NO_ERROR) {
1153 LOGV("wait - success");
1154 } else {
1155 LOGV("wait - error");
1156 }
1157 return mError;
1158}
1159
1160void MediaPlayerService::AudioCache::notify(void* cookie, int msg, int ext1, int ext2)
1161{
1162 LOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
1163 AudioCache* p = static_cast<AudioCache*>(cookie);
1164
1165 // ignore buffering messages
1166 if (msg == MEDIA_BUFFERING_UPDATE) return;
1167
1168 // set error condition
1169 if (msg == MEDIA_ERROR) {
1170 LOGE("Error %d, %d occurred", ext1, ext2);
1171 p->mError = ext1;
1172 }
1173
1174 // wake up thread
1175 LOGV("wakeup thread");
1176 p->mCommandComplete = true;
1177 p->mSignal.signal();
1178}
1179
1180}; // namespace android