The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* |
| 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 | //#define LOG_NDEBUG 0 |
| 19 | #define LOG_TAG "MediaMetadataRetriever" |
| 20 | |
Mathias Agopian | 0795272 | 2009-05-19 19:08:10 -0700 | [diff] [blame] | 21 | #include <binder/IServiceManager.h> |
| 22 | #include <binder/IPCThreadState.h> |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 23 | #include <media/mediametadataretriever.h> |
| 24 | #include <media/IMediaPlayerService.h> |
| 25 | #include <utils/Log.h> |
| 26 | #include <dlfcn.h> |
| 27 | |
| 28 | namespace android { |
| 29 | |
| 30 | // client singleton for binder interface to service |
| 31 | Mutex MediaMetadataRetriever::sServiceLock; |
| 32 | sp<IMediaPlayerService> MediaMetadataRetriever::sService; |
| 33 | sp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier; |
| 34 | |
| 35 | const sp<IMediaPlayerService>& MediaMetadataRetriever::getService() |
| 36 | { |
| 37 | Mutex::Autolock lock(sServiceLock); |
Glenn Kasten | 70ed6b7 | 2012-01-10 10:46:34 -0800 | [diff] [blame] | 38 | if (sService == 0) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 39 | sp<IServiceManager> sm = defaultServiceManager(); |
| 40 | sp<IBinder> binder; |
| 41 | do { |
| 42 | binder = sm->getService(String16("media.player")); |
| 43 | if (binder != 0) { |
| 44 | break; |
| 45 | } |
Steve Block | 8564c8d | 2012-01-05 23:22:43 +0000 | [diff] [blame] | 46 | ALOGW("MediaPlayerService not published, waiting..."); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 47 | usleep(500000); // 0.5 s |
Glenn Kasten | 18db49a | 2012-03-12 16:29:55 -0700 | [diff] [blame^] | 48 | } while (true); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 49 | if (sDeathNotifier == NULL) { |
| 50 | sDeathNotifier = new DeathNotifier(); |
| 51 | } |
| 52 | binder->linkToDeath(sDeathNotifier); |
| 53 | sService = interface_cast<IMediaPlayerService>(binder); |
| 54 | } |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 55 | ALOGE_IF(sService == 0, "no MediaPlayerService!?"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 56 | return sService; |
| 57 | } |
| 58 | |
| 59 | MediaMetadataRetriever::MediaMetadataRetriever() |
| 60 | { |
Steve Block | 71f2cf1 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 61 | ALOGV("constructor"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 62 | const sp<IMediaPlayerService>& service(getService()); |
| 63 | if (service == 0) { |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 64 | ALOGE("failed to obtain MediaMetadataRetrieverService"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 65 | return; |
| 66 | } |
| 67 | sp<IMediaMetadataRetriever> retriever(service->createMetadataRetriever(getpid())); |
| 68 | if (retriever == 0) { |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 69 | ALOGE("failed to create IMediaMetadataRetriever object from server"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 70 | } |
| 71 | mRetriever = retriever; |
| 72 | } |
| 73 | |
| 74 | MediaMetadataRetriever::~MediaMetadataRetriever() |
| 75 | { |
Steve Block | 71f2cf1 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 76 | ALOGV("destructor"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 77 | disconnect(); |
| 78 | IPCThreadState::self()->flushCommands(); |
| 79 | } |
| 80 | |
| 81 | void MediaMetadataRetriever::disconnect() |
| 82 | { |
Steve Block | 71f2cf1 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 83 | ALOGV("disconnect"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 84 | sp<IMediaMetadataRetriever> retriever; |
| 85 | { |
| 86 | Mutex::Autolock _l(mLock); |
| 87 | retriever = mRetriever; |
| 88 | mRetriever.clear(); |
| 89 | } |
| 90 | if (retriever != 0) { |
| 91 | retriever->disconnect(); |
| 92 | } |
| 93 | } |
| 94 | |
Andreas Huber | 5b7ced6 | 2011-03-21 10:25:44 -0700 | [diff] [blame] | 95 | status_t MediaMetadataRetriever::setDataSource( |
| 96 | const char *srcUrl, const KeyedVector<String8, String8> *headers) |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 97 | { |
Steve Block | 71f2cf1 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 98 | ALOGV("setDataSource"); |
Dave Sparks | db6cc0b | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 99 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 100 | if (mRetriever == 0) { |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 101 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 102 | return INVALID_OPERATION; |
| 103 | } |
| 104 | if (srcUrl == NULL) { |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 105 | ALOGE("data source is a null pointer"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 106 | return UNKNOWN_ERROR; |
| 107 | } |
Steve Block | 71f2cf1 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 108 | ALOGV("data source (%s)", srcUrl); |
Andreas Huber | 5b7ced6 | 2011-03-21 10:25:44 -0700 | [diff] [blame] | 109 | return mRetriever->setDataSource(srcUrl, headers); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 110 | } |
| 111 | |
| 112 | status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) |
| 113 | { |
Steve Block | 71f2cf1 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 114 | ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); |
Dave Sparks | db6cc0b | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 115 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 116 | if (mRetriever == 0) { |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 117 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 118 | return INVALID_OPERATION; |
| 119 | } |
| 120 | if (fd < 0 || offset < 0 || length < 0) { |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 121 | ALOGE("Invalid negative argument"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 122 | return UNKNOWN_ERROR; |
| 123 | } |
| 124 | return mRetriever->setDataSource(fd, offset, length); |
| 125 | } |
| 126 | |
James Dong | faf09ba | 2010-12-02 17:42:08 -0800 | [diff] [blame] | 127 | sp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option) |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 128 | { |
Steve Block | 71f2cf1 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 129 | ALOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option); |
Dave Sparks | db6cc0b | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 130 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 131 | if (mRetriever == 0) { |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 132 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 133 | return NULL; |
| 134 | } |
James Dong | faf09ba | 2010-12-02 17:42:08 -0800 | [diff] [blame] | 135 | return mRetriever->getFrameAtTime(timeUs, option); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 136 | } |
| 137 | |
| 138 | const char* MediaMetadataRetriever::extractMetadata(int keyCode) |
| 139 | { |
Steve Block | 71f2cf1 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 140 | ALOGV("extractMetadata(%d)", keyCode); |
Dave Sparks | db6cc0b | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 141 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 142 | if (mRetriever == 0) { |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 143 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 144 | return NULL; |
| 145 | } |
| 146 | return mRetriever->extractMetadata(keyCode); |
| 147 | } |
| 148 | |
| 149 | sp<IMemory> MediaMetadataRetriever::extractAlbumArt() |
| 150 | { |
Steve Block | 71f2cf1 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 151 | ALOGV("extractAlbumArt"); |
Dave Sparks | db6cc0b | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 152 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 153 | if (mRetriever == 0) { |
Steve Block | 3762c31 | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 154 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 155 | return NULL; |
| 156 | } |
| 157 | return mRetriever->extractAlbumArt(); |
| 158 | } |
| 159 | |
| 160 | void MediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>& who) { |
| 161 | Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock); |
| 162 | MediaMetadataRetriever::sService.clear(); |
Steve Block | 8564c8d | 2012-01-05 23:22:43 +0000 | [diff] [blame] | 163 | ALOGW("MediaMetadataRetriever server died!"); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 164 | } |
| 165 | |
| 166 | MediaMetadataRetriever::DeathNotifier::~DeathNotifier() |
| 167 | { |
| 168 | Mutex::Autolock lock(sServiceLock); |
| 169 | if (sService != 0) { |
| 170 | sService->asBinder()->unlinkToDeath(this); |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | }; // namespace android |