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); |
| 38 | if (sService.get() == 0) { |
| 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 | } |
| 46 | LOGW("MediaPlayerService not published, waiting..."); |
| 47 | usleep(500000); // 0.5 s |
| 48 | } while(true); |
| 49 | if (sDeathNotifier == NULL) { |
| 50 | sDeathNotifier = new DeathNotifier(); |
| 51 | } |
| 52 | binder->linkToDeath(sDeathNotifier); |
| 53 | sService = interface_cast<IMediaPlayerService>(binder); |
| 54 | } |
| 55 | LOGE_IF(sService == 0, "no MediaPlayerService!?"); |
| 56 | return sService; |
| 57 | } |
| 58 | |
| 59 | MediaMetadataRetriever::MediaMetadataRetriever() |
| 60 | { |
| 61 | LOGV("constructor"); |
| 62 | const sp<IMediaPlayerService>& service(getService()); |
| 63 | if (service == 0) { |
| 64 | LOGE("failed to obtain MediaMetadataRetrieverService"); |
| 65 | return; |
| 66 | } |
| 67 | sp<IMediaMetadataRetriever> retriever(service->createMetadataRetriever(getpid())); |
| 68 | if (retriever == 0) { |
| 69 | LOGE("failed to create IMediaMetadataRetriever object from server"); |
| 70 | } |
| 71 | mRetriever = retriever; |
| 72 | } |
| 73 | |
| 74 | MediaMetadataRetriever::~MediaMetadataRetriever() |
| 75 | { |
| 76 | LOGV("destructor"); |
| 77 | disconnect(); |
| 78 | IPCThreadState::self()->flushCommands(); |
| 79 | } |
| 80 | |
| 81 | void MediaMetadataRetriever::disconnect() |
| 82 | { |
| 83 | LOGV("disconnect"); |
| 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 | { |
| 98 | LOGV("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) { |
| 101 | LOGE("retriever is not initialized"); |
| 102 | return INVALID_OPERATION; |
| 103 | } |
| 104 | if (srcUrl == NULL) { |
| 105 | LOGE("data source is a null pointer"); |
| 106 | return UNKNOWN_ERROR; |
| 107 | } |
| 108 | LOGV("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 | { |
| 114 | LOGV("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) { |
| 117 | LOGE("retriever is not initialized"); |
| 118 | return INVALID_OPERATION; |
| 119 | } |
| 120 | if (fd < 0 || offset < 0 || length < 0) { |
| 121 | LOGE("Invalid negative argument"); |
| 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 | { |
James Dong | faf09ba | 2010-12-02 17:42:08 -0800 | [diff] [blame] | 129 | LOGV("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) { |
| 132 | LOGE("retriever is not initialized"); |
| 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 | { |
| 140 | LOGV("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) { |
| 143 | LOGE("retriever is not initialized"); |
| 144 | return NULL; |
| 145 | } |
| 146 | return mRetriever->extractMetadata(keyCode); |
| 147 | } |
| 148 | |
| 149 | sp<IMemory> MediaMetadataRetriever::extractAlbumArt() |
| 150 | { |
| 151 | LOGV("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) { |
| 154 | LOGE("retriever is not initialized"); |
| 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(); |
| 163 | LOGW("MediaMetadataRetriever server died!"); |
| 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 |