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 | |
Marco Nelissen | 61a6d26 | 2016-02-18 08:25:47 -0800 | [diff] [blame] | 38 | const sp<IMediaPlayerService> MediaMetadataRetriever::getService() |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 39 | { |
| 40 | Mutex::Autolock lock(sServiceLock); |
Glenn Kasten | 7fc9a6f | 2012-01-10 10:46:34 -0800 | [diff] [blame] | 41 | if (sService == 0) { |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 42 | sp<IServiceManager> sm = defaultServiceManager(); |
| 43 | sp<IBinder> binder; |
Yifei Zhang | ff21209 | 2023-06-02 11:59:41 -0700 | [diff] [blame] | 44 | binder = sm->waitForService(String16("media.player")); |
| 45 | if (binder == nullptr) { |
| 46 | return nullptr; |
| 47 | } |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 48 | if (sDeathNotifier == NULL) { |
| 49 | sDeathNotifier = new DeathNotifier(); |
| 50 | } |
| 51 | binder->linkToDeath(sDeathNotifier); |
| 52 | sService = interface_cast<IMediaPlayerService>(binder); |
| 53 | } |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 54 | ALOGE_IF(sService == 0, "no MediaPlayerService!?"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 55 | return sService; |
| 56 | } |
| 57 | |
| 58 | MediaMetadataRetriever::MediaMetadataRetriever() |
| 59 | { |
Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 60 | ALOGV("constructor"); |
Marco Nelissen | 61a6d26 | 2016-02-18 08:25:47 -0800 | [diff] [blame] | 61 | const sp<IMediaPlayerService> service(getService()); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 62 | if (service == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 63 | ALOGE("failed to obtain MediaMetadataRetrieverService"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 64 | return; |
| 65 | } |
Glenn Kasten | 8d6cc84 | 2012-02-03 11:06:53 -0800 | [diff] [blame] | 66 | sp<IMediaMetadataRetriever> retriever(service->createMetadataRetriever()); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 67 | if (retriever == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 68 | ALOGE("failed to create IMediaMetadataRetriever object from server"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 69 | } |
| 70 | mRetriever = retriever; |
| 71 | } |
| 72 | |
| 73 | MediaMetadataRetriever::~MediaMetadataRetriever() |
| 74 | { |
Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 75 | ALOGV("destructor"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 76 | disconnect(); |
| 77 | IPCThreadState::self()->flushCommands(); |
| 78 | } |
| 79 | |
| 80 | void MediaMetadataRetriever::disconnect() |
| 81 | { |
Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 82 | ALOGV("disconnect"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 83 | sp<IMediaMetadataRetriever> retriever; |
| 84 | { |
| 85 | Mutex::Autolock _l(mLock); |
| 86 | retriever = mRetriever; |
| 87 | mRetriever.clear(); |
| 88 | } |
| 89 | if (retriever != 0) { |
| 90 | retriever->disconnect(); |
| 91 | } |
| 92 | } |
| 93 | |
Andreas Huber | af8791e | 2011-03-21 10:25:44 -0700 | [diff] [blame] | 94 | status_t MediaMetadataRetriever::setDataSource( |
Andreas Huber | 1b86fe0 | 2014-01-29 11:13:26 -0800 | [diff] [blame] | 95 | const sp<IMediaHTTPService> &httpService, |
| 96 | const char *srcUrl, |
| 97 | const KeyedVector<String8, String8> *headers) |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 98 | { |
Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 99 | ALOGV("setDataSource"); |
Dave Sparks | a17a134 | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 100 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 101 | if (mRetriever == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 102 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 103 | return INVALID_OPERATION; |
| 104 | } |
| 105 | if (srcUrl == NULL) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 106 | ALOGE("data source is a null pointer"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 107 | return UNKNOWN_ERROR; |
| 108 | } |
Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 109 | ALOGV("data source (%s)", srcUrl); |
Andreas Huber | 1b86fe0 | 2014-01-29 11:13:26 -0800 | [diff] [blame] | 110 | return mRetriever->setDataSource(httpService, srcUrl, headers); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) |
| 114 | { |
Mark Salyzyn | 34fb296 | 2014-06-18 16:30:56 -0700 | [diff] [blame] | 115 | ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); |
Dave Sparks | a17a134 | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 116 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 117 | if (mRetriever == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 118 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 119 | return INVALID_OPERATION; |
| 120 | } |
| 121 | if (fd < 0 || offset < 0 || length < 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 122 | ALOGE("Invalid negative argument"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 123 | return UNKNOWN_ERROR; |
| 124 | } |
| 125 | return mRetriever->setDataSource(fd, offset, length); |
| 126 | } |
| 127 | |
Chris Watkins | 99f3160 | 2015-03-20 13:06:33 -0700 | [diff] [blame] | 128 | status_t MediaMetadataRetriever::setDataSource( |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 129 | const sp<IDataSource>& dataSource, const char *mime) |
Chris Watkins | 99f3160 | 2015-03-20 13:06:33 -0700 | [diff] [blame] | 130 | { |
| 131 | ALOGV("setDataSource(IDataSource)"); |
| 132 | Mutex::Autolock _l(mLock); |
| 133 | if (mRetriever == 0) { |
| 134 | ALOGE("retriever is not initialized"); |
| 135 | return INVALID_OPERATION; |
| 136 | } |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 137 | return mRetriever->setDataSource(dataSource, mime); |
Chris Watkins | 99f3160 | 2015-03-20 13:06:33 -0700 | [diff] [blame] | 138 | } |
| 139 | |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 140 | sp<IMemory> MediaMetadataRetriever::getFrameAtTime( |
| 141 | int64_t timeUs, int option, int colorFormat, bool metaOnly) |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 142 | { |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 143 | ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d) colorFormat(%d) metaOnly(%d)", |
| 144 | timeUs, option, colorFormat, metaOnly); |
Dave Sparks | a17a134 | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 145 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 146 | if (mRetriever == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 147 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 148 | return NULL; |
| 149 | } |
Chong Zhang | 24c1577 | 2017-07-26 16:25:28 -0700 | [diff] [blame] | 150 | return mRetriever->getFrameAtTime(timeUs, option, colorFormat, metaOnly); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 151 | } |
| 152 | |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 153 | sp<IMemory> MediaMetadataRetriever::getImageAtIndex( |
Chong Zhang | d5fa357 | 2018-04-09 19:03:10 -0700 | [diff] [blame] | 154 | int index, int colorFormat, bool metaOnly, bool thumbnail) { |
| 155 | ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)", |
| 156 | index, colorFormat, metaOnly, thumbnail); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 157 | Mutex::Autolock _l(mLock); |
| 158 | if (mRetriever == 0) { |
| 159 | ALOGE("retriever is not initialized"); |
| 160 | return NULL; |
| 161 | } |
Chong Zhang | d5fa357 | 2018-04-09 19:03:10 -0700 | [diff] [blame] | 162 | return mRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 163 | } |
| 164 | |
Chong Zhang | 0c1407f | 2018-05-02 17:09:05 -0700 | [diff] [blame] | 165 | sp<IMemory> MediaMetadataRetriever::getImageRectAtIndex( |
| 166 | int index, int colorFormat, int left, int top, int right, int bottom) { |
| 167 | ALOGV("getImageRectAtIndex: index(%d) colorFormat(%d) rect {%d, %d, %d, %d}", |
| 168 | index, colorFormat, left, top, right, bottom); |
| 169 | Mutex::Autolock _l(mLock); |
| 170 | if (mRetriever == 0) { |
| 171 | ALOGE("retriever is not initialized"); |
| 172 | return NULL; |
| 173 | } |
| 174 | return mRetriever->getImageRectAtIndex( |
| 175 | index, colorFormat, left, top, right, bottom); |
| 176 | } |
| 177 | |
Chong Zhang | 76a49d6 | 2019-07-12 11:20:33 -0700 | [diff] [blame] | 178 | sp<IMemory> MediaMetadataRetriever::getFrameAtIndex( |
| 179 | int index, int colorFormat, bool metaOnly) { |
| 180 | ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)", |
| 181 | index, colorFormat, metaOnly); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 182 | Mutex::Autolock _l(mLock); |
| 183 | if (mRetriever == 0) { |
| 184 | ALOGE("retriever is not initialized"); |
Chong Zhang | 76a49d6 | 2019-07-12 11:20:33 -0700 | [diff] [blame] | 185 | return NULL; |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 186 | } |
Chong Zhang | 76a49d6 | 2019-07-12 11:20:33 -0700 | [diff] [blame] | 187 | return mRetriever->getFrameAtIndex(index, colorFormat, metaOnly); |
Chong Zhang | d3e0d86 | 2017-10-03 13:17:13 -0700 | [diff] [blame] | 188 | } |
| 189 | |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 190 | const char* MediaMetadataRetriever::extractMetadata(int keyCode) |
| 191 | { |
Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 192 | ALOGV("extractMetadata(%d)", keyCode); |
Dave Sparks | a17a134 | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 193 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 194 | if (mRetriever == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 195 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 196 | return NULL; |
| 197 | } |
| 198 | return mRetriever->extractMetadata(keyCode); |
| 199 | } |
| 200 | |
| 201 | sp<IMemory> MediaMetadataRetriever::extractAlbumArt() |
| 202 | { |
Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 203 | ALOGV("extractAlbumArt"); |
Dave Sparks | a17a134 | 2010-04-01 18:00:58 -0700 | [diff] [blame] | 204 | Mutex::Autolock _l(mLock); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 205 | if (mRetriever == 0) { |
Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 206 | ALOGE("retriever is not initialized"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 207 | return NULL; |
| 208 | } |
| 209 | return mRetriever->extractAlbumArt(); |
| 210 | } |
| 211 | |
Glenn Kasten | 7c7be1e | 2013-12-19 16:34:04 -0800 | [diff] [blame] | 212 | void MediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>& who __unused) { |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 213 | Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock); |
| 214 | MediaMetadataRetriever::sService.clear(); |
Steve Block | 5ff1dd5 | 2012-01-05 23:22:43 +0000 | [diff] [blame] | 215 | ALOGW("MediaMetadataRetriever server died!"); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 216 | } |
| 217 | |
| 218 | MediaMetadataRetriever::DeathNotifier::~DeathNotifier() |
| 219 | { |
| 220 | Mutex::Autolock lock(sServiceLock); |
| 221 | if (sService != 0) { |
Marco Nelissen | 06b4606 | 2014-11-14 07:58:25 -0800 | [diff] [blame] | 222 | IInterface::asBinder(sService)->unlinkToDeath(this); |
The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 223 | } |
| 224 | } |
| 225 | |
Glenn Kasten | 40bc906 | 2015-03-20 09:09:33 -0700 | [diff] [blame] | 226 | } // namespace android |