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 | |
Mark Salyzyn | 34fb296 | 2014-06-18 16:30:56 -0700 | [diff] [blame] | 21 | #include <inttypes.h> |
| 22 | |
Mathias Agopian | 7562408 | 2009-05-19 19:08:10 -0700 | [diff] [blame] | 23 | #include <binder/IServiceManager.h> |
| 24 | #include <binder/IPCThreadState.h> |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 25 | #include <media/mediametadataretriever.h> |
Andreas Huber | 1b86fe0 | 2014-01-29 11:13:26 -0800 | [diff] [blame] | 26 | #include <media/IMediaHTTPService.h> |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 27 | #include <media/IMediaPlayerService.h> |
| 28 | #include <utils/Log.h> |
| 29 | #include <dlfcn.h> |
| 30 | |
| 31 | namespace android { |
| 32 | |
| 33 | // client singleton for binder interface to service |
| 34 | Mutex MediaMetadataRetriever::sServiceLock; |
| 35 | sp<IMediaPlayerService> MediaMetadataRetriever::sService; |
| 36 | sp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier; |
| 37 | |
Sungtak Lee | d33e319 | 2024-09-25 23:27:58 +0000 | [diff] [blame] | 38 | Mutex MediaMetadataRetriever::sLock; |
| 39 | |
Marco Nelissen | 61a6d26 | 2016-02-18 08:25:47 -0800 | [diff] [blame] | 40 | const sp<IMediaPlayerService> MediaMetadataRetriever::getService() |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 41 | { |
| 42 | Mutex::Autolock lock(sServiceLock); |
Glenn Kasten | 7fc9a6f | 2012-01-10 10:46:34 -0800 | [diff] [blame] | 43 | if (sService == 0) { |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 44 | sp<IServiceManager> sm = defaultServiceManager(); |
| 45 | sp<IBinder> binder; |
Yifei Zhang | ff21209 | 2023-06-02 11:59:41 -0700 | [diff] [blame] | 46 | binder = sm->waitForService(String16("media.player")); |
| 47 | if (binder == nullptr) { |
| 48 | return nullptr; |
| 49 | } |
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"); |
Marco Nelissen | 61a6d26 | 2016-02-18 08:25:47 -0800 | [diff] [blame] | 63 | const sp<IMediaPlayerService> service(getService()); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | { |
Mark Salyzyn | 34fb296 | 2014-06-18 16:30:56 -0700 | [diff] [blame] | 117 | ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", 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 | |
Chris Watkins | 99f3160 | 2015-03-20 13:06:33 -0700 | [diff] [blame] | 130 | status_t MediaMetadataRetriever::setDataSource( |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 131 | const sp<IDataSource>& dataSource, const char *mime) |
Chris Watkins | 99f3160 | 2015-03-20 13:06:33 -0700 | [diff] [blame] | 132 | { |
| 133 | ALOGV("setDataSource(IDataSource)"); |
| 134 | Mutex::Autolock _l(mLock); |
| 135 | if (mRetriever == 0) { |
| 136 | ALOGE("retriever is not initialized"); |
| 137 | return INVALID_OPERATION; |
| 138 | } |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 139 | return mRetriever->setDataSource(dataSource, mime); |
Chris Watkins | 99f3160 | 2015-03-20 13:06:33 -0700 | [diff] [blame] | 140 | } |
| 141 | |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 142 | sp<IMemory> MediaMetadataRetriever::getFrameAtTime( |
| 143 | int64_t timeUs, int option, int colorFormat, bool metaOnly) |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 144 | { |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 145 | ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d) colorFormat(%d) metaOnly(%d)", |
| 146 | timeUs, option, colorFormat, metaOnly); |
Dave Sparks | a17a134 | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 147 | Mutex::Autolock _l(mLock); |
Sungtak Lee | d33e319 | 2024-09-25 23:27:58 +0000 | [diff] [blame] | 148 | Mutex::Autolock _gLock(sLock); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 149 | if (mRetriever == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 150 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 151 | return NULL; |
| 152 | } |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 153 | return mRetriever->getFrameAtTime(timeUs, option, colorFormat, metaOnly); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 154 | } |
| 155 | |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 156 | sp<IMemory> MediaMetadataRetriever::getImageAtIndex( |
Chong Zhang | d5fa357 | 2018-04-09 19:03:10 -0700 | [diff] [blame] | 157 | int index, int colorFormat, bool metaOnly, bool thumbnail) { |
| 158 | ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)", |
| 159 | index, colorFormat, metaOnly, thumbnail); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 160 | Mutex::Autolock _l(mLock); |
Sungtak Lee | d33e319 | 2024-09-25 23:27:58 +0000 | [diff] [blame] | 161 | Mutex::Autolock _gLock(sLock); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 162 | if (mRetriever == 0) { |
| 163 | ALOGE("retriever is not initialized"); |
| 164 | return NULL; |
| 165 | } |
Chong Zhang | d5fa357 | 2018-04-09 19:03:10 -0700 | [diff] [blame] | 166 | return mRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 167 | } |
| 168 | |
Chong Zhang | 0c1407f | 2018-05-02 17:09:05 -0700 | [diff] [blame] | 169 | sp<IMemory> MediaMetadataRetriever::getImageRectAtIndex( |
| 170 | int index, int colorFormat, int left, int top, int right, int bottom) { |
| 171 | ALOGV("getImageRectAtIndex: index(%d) colorFormat(%d) rect {%d, %d, %d, %d}", |
| 172 | index, colorFormat, left, top, right, bottom); |
| 173 | Mutex::Autolock _l(mLock); |
Sungtak Lee | d33e319 | 2024-09-25 23:27:58 +0000 | [diff] [blame] | 174 | Mutex::Autolock _gLock(sLock); |
Chong Zhang | 0c1407f | 2018-05-02 17:09:05 -0700 | [diff] [blame] | 175 | if (mRetriever == 0) { |
| 176 | ALOGE("retriever is not initialized"); |
| 177 | return NULL; |
| 178 | } |
| 179 | return mRetriever->getImageRectAtIndex( |
| 180 | index, colorFormat, left, top, right, bottom); |
| 181 | } |
| 182 | |
Chong Zhang | 76a49d6 | 2019-07-12 11:20:33 -0700 | [diff] [blame] | 183 | sp<IMemory> MediaMetadataRetriever::getFrameAtIndex( |
| 184 | int index, int colorFormat, bool metaOnly) { |
| 185 | ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)", |
| 186 | index, colorFormat, metaOnly); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 187 | Mutex::Autolock _l(mLock); |
Sungtak Lee | d33e319 | 2024-09-25 23:27:58 +0000 | [diff] [blame] | 188 | Mutex::Autolock _gLock(sLock); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 189 | if (mRetriever == 0) { |
| 190 | ALOGE("retriever is not initialized"); |
Chong Zhang | 76a49d6 | 2019-07-12 11:20:33 -0700 | [diff] [blame] | 191 | return NULL; |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 192 | } |
Chong Zhang | 76a49d6 | 2019-07-12 11:20:33 -0700 | [diff] [blame] | 193 | return mRetriever->getFrameAtIndex(index, colorFormat, metaOnly); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 194 | } |
| 195 | |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 196 | const char* MediaMetadataRetriever::extractMetadata(int keyCode) |
| 197 | { |
Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 198 | ALOGV("extractMetadata(%d)", keyCode); |
Dave Sparks | a17a134 | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 199 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 200 | if (mRetriever == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 201 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 202 | return NULL; |
| 203 | } |
| 204 | return mRetriever->extractMetadata(keyCode); |
| 205 | } |
| 206 | |
| 207 | sp<IMemory> MediaMetadataRetriever::extractAlbumArt() |
| 208 | { |
Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 209 | ALOGV("extractAlbumArt"); |
Dave Sparks | a17a134 | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 210 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 211 | if (mRetriever == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 212 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 213 | return NULL; |
| 214 | } |
| 215 | return mRetriever->extractAlbumArt(); |
| 216 | } |
| 217 | |
Glenn Kasten | 7c7be1e | 2013-12-19 16:34:04 -0800 | [diff] [blame] | 218 | void MediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>& who __unused) { |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 219 | Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock); |
| 220 | MediaMetadataRetriever::sService.clear(); |
Steve Block | 5ff1dd5 | 2012-01-05 23:22:43 +0000 | [diff] [blame] | 221 | ALOGW("MediaMetadataRetriever server died!"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 222 | } |
| 223 | |
| 224 | MediaMetadataRetriever::DeathNotifier::~DeathNotifier() |
| 225 | { |
| 226 | Mutex::Autolock lock(sServiceLock); |
| 227 | if (sService != 0) { |
Marco Nelissen | 06b4606 | 2014-11-14 07:58:25 -0800 | [diff] [blame] | 228 | IInterface::asBinder(sService)->unlinkToDeath(this); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 229 | } |
| 230 | } |
| 231 | |
Glenn Kasten | 40bc906 | 2015-03-20 09:09:33 -0700 | [diff] [blame] | 232 | } // namespace android |