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