MetadataRetrieverClient.cpp revision 065c05e72091567632f927d9e5411e277480c1bf
1/* 2** 3** Copyright (C) 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 "MetadataRetrieverClient" 20#include <utils/Log.h> 21 22#include <sys/types.h> 23#include <sys/stat.h> 24#include <sys/resource.h> 25#include <dirent.h> 26#include <unistd.h> 27 28#include <string.h> 29#include <cutils/atomic.h> 30#include <cutils/properties.h> 31#include <binder/MemoryDealer.h> 32#include <android_runtime/ActivityManager.h> 33#include <binder/IPCThreadState.h> 34#include <binder/IServiceManager.h> 35#include <media/MediaMetadataRetrieverInterface.h> 36#include <media/MediaPlayerInterface.h> 37#include <media/PVMetadataRetriever.h> 38#include <private/media/VideoFrame.h> 39#include "VorbisMetadataRetriever.h" 40#include "MidiMetadataRetriever.h" 41#include "MetadataRetrieverClient.h" 42#include "StagefrightMetadataRetriever.h" 43 44/* desktop Linux needs a little help with gettid() */ 45#if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS) 46#define __KERNEL__ 47# include <linux/unistd.h> 48#ifdef _syscall0 49_syscall0(pid_t,gettid) 50#else 51pid_t gettid() { return syscall(__NR_gettid);} 52#endif 53#undef __KERNEL__ 54#endif 55 56namespace android { 57 58extern player_type getPlayerType(const char* url); 59extern player_type getPlayerType(int fd, int64_t offset, int64_t length); 60 61MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid) 62{ 63 LOGV("MetadataRetrieverClient constructor pid(%d)", pid); 64 mPid = pid; 65 mThumbnailDealer = NULL; 66 mAlbumArtDealer = NULL; 67 mThumbnail = NULL; 68 mAlbumArt = NULL; 69 mRetriever = NULL; 70 mMode = METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL; 71} 72 73MetadataRetrieverClient::~MetadataRetrieverClient() 74{ 75 LOGV("MetadataRetrieverClient destructor"); 76 disconnect(); 77} 78 79status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& args) const 80{ 81 const size_t SIZE = 256; 82 char buffer[SIZE]; 83 String8 result; 84 result.append(" MetadataRetrieverClient\n"); 85 snprintf(buffer, 255, " pid(%d) mode(%d)\n", mPid, mMode); 86 result.append(buffer); 87 write(fd, result.string(), result.size()); 88 write(fd, "\n", 1); 89 return NO_ERROR; 90} 91 92void MetadataRetrieverClient::disconnect() 93{ 94 LOGV("disconnect from pid %d", mPid); 95 Mutex::Autolock lock(mLock); 96 mRetriever.clear(); 97 mThumbnailDealer.clear(); 98 mAlbumArtDealer.clear(); 99 mThumbnail.clear(); 100 mAlbumArt.clear(); 101 mMode = METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL; 102 IPCThreadState::self()->flushCommands(); 103} 104 105static sp<MediaMetadataRetrieverBase> createRetriever(player_type playerType) 106{ 107 sp<MediaMetadataRetrieverBase> p; 108 switch (playerType) { 109#if BUILD_WITH_FULL_STAGEFRIGHT 110 case STAGEFRIGHT_PLAYER: 111 { 112 char value[PROPERTY_VALUE_MAX]; 113 if (property_get("media.stagefright.enable-meta", value, NULL) 114 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 115 LOGV("create StagefrightMetadataRetriever"); 116 p = new StagefrightMetadataRetriever; 117 break; 118 } 119 120 // fall through 121 } 122#endif 123#ifndef NO_OPENCORE 124 case PV_PLAYER: 125 LOGV("create pv metadata retriever"); 126 p = new PVMetadataRetriever(); 127 break; 128#endif 129 case VORBIS_PLAYER: 130 LOGV("create vorbis metadata retriever"); 131 p = new VorbisMetadataRetriever(); 132 break; 133 case SONIVOX_PLAYER: 134 LOGV("create midi metadata retriever"); 135 p = new MidiMetadataRetriever(); 136 break; 137 default: 138 // TODO: 139 // support for TEST_PLAYER 140 LOGE("player type %d is not supported", playerType); 141 break; 142 } 143 if (p == NULL) { 144 LOGE("failed to create a retriever object"); 145 } 146 return p; 147} 148 149status_t MetadataRetrieverClient::setDataSource(const char *url) 150{ 151 LOGV("setDataSource(%s)", url); 152 Mutex::Autolock lock(mLock); 153 if (url == NULL) { 154 return UNKNOWN_ERROR; 155 } 156 player_type playerType = getPlayerType(url); 157 LOGV("player type = %d", playerType); 158 sp<MediaMetadataRetrieverBase> p = createRetriever(playerType); 159 if (p == NULL) return NO_INIT; 160 status_t ret = p->setMode(mMode); 161 if (ret == NO_ERROR) { 162 ret = p->setDataSource(url); 163 } 164 if (ret == NO_ERROR) mRetriever = p; 165 return ret; 166} 167 168status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length) 169{ 170 LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length); 171 Mutex::Autolock lock(mLock); 172 struct stat sb; 173 int ret = fstat(fd, &sb); 174 if (ret != 0) { 175 LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno)); 176 return BAD_VALUE; 177 } 178 LOGV("st_dev = %llu", sb.st_dev); 179 LOGV("st_mode = %u", sb.st_mode); 180 LOGV("st_uid = %lu", sb.st_uid); 181 LOGV("st_gid = %lu", sb.st_gid); 182 LOGV("st_size = %llu", sb.st_size); 183 184 if (offset >= sb.st_size) { 185 LOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size); 186 ::close(fd); 187 return BAD_VALUE; 188 } 189 if (offset + length > sb.st_size) { 190 length = sb.st_size - offset; 191 LOGV("calculated length = %lld", length); 192 } 193 194 player_type playerType = getPlayerType(fd, offset, length); 195 LOGV("player type = %d", playerType); 196 sp<MediaMetadataRetrieverBase> p = createRetriever(playerType); 197 if (p == NULL) { 198 ::close(fd); 199 return NO_INIT; 200 } 201 status_t status = p->setMode(mMode); 202 if (status == NO_ERROR) { 203 p->setDataSource(fd, offset, length); 204 } 205 if (status == NO_ERROR) mRetriever = p; 206 ::close(fd); 207 return status; 208} 209 210status_t MetadataRetrieverClient::setMode(int mode) 211{ 212 LOGV("setMode"); 213 Mutex::Autolock lock(mLock); 214 if (mode < METADATA_MODE_NOOP || 215 mode > METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL) { 216 LOGE("invalid mode %d", mode); 217 return BAD_VALUE; 218 } 219 mMode = mode; 220 return NO_ERROR; 221} 222 223status_t MetadataRetrieverClient::getMode(int* mode) const 224{ 225 LOGV("getMode"); 226 Mutex::Autolock lock(mLock); 227 228 // TODO: 229 // This may not be necessary. 230 // If setDataSource() has not been called, return the cached value 231 // otherwise, return the value retrieved from the retriever 232 if (mRetriever == NULL) { 233 *mode = mMode; 234 } else { 235 mRetriever->getMode(mode); 236 } 237 return NO_ERROR; 238} 239 240sp<IMemory> MetadataRetrieverClient::captureFrame() 241{ 242 LOGV("captureFrame"); 243 Mutex::Autolock lock(mLock); 244 mThumbnail.clear(); 245 mThumbnailDealer.clear(); 246 if (mRetriever == NULL) { 247 LOGE("retriever is not initialized"); 248 return NULL; 249 } 250 VideoFrame *frame = mRetriever->captureFrame(); 251 if (frame == NULL) { 252 LOGE("failed to capture a video frame"); 253 return NULL; 254 } 255 size_t size = sizeof(VideoFrame) + frame->mSize; 256 mThumbnailDealer = new MemoryDealer(size); 257 if (mThumbnailDealer == NULL) { 258 LOGE("failed to create MemoryDealer"); 259 delete frame; 260 return NULL; 261 } 262 mThumbnail = mThumbnailDealer->allocate(size); 263 if (mThumbnail == NULL) { 264 LOGE("not enough memory for VideoFrame size=%u", size); 265 mThumbnailDealer.clear(); 266 delete frame; 267 return NULL; 268 } 269 VideoFrame *frameCopy = static_cast<VideoFrame *>(mThumbnail->pointer()); 270 frameCopy->mWidth = frame->mWidth; 271 frameCopy->mHeight = frame->mHeight; 272 frameCopy->mDisplayWidth = frame->mDisplayWidth; 273 frameCopy->mDisplayHeight = frame->mDisplayHeight; 274 frameCopy->mSize = frame->mSize; 275 frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame); 276 memcpy(frameCopy->mData, frame->mData, frame->mSize); 277 delete frame; // Fix memory leakage 278 return mThumbnail; 279} 280 281sp<IMemory> MetadataRetrieverClient::extractAlbumArt() 282{ 283 LOGV("extractAlbumArt"); 284 Mutex::Autolock lock(mLock); 285 mAlbumArt.clear(); 286 mAlbumArtDealer.clear(); 287 if (mRetriever == NULL) { 288 LOGE("retriever is not initialized"); 289 return NULL; 290 } 291 MediaAlbumArt *albumArt = mRetriever->extractAlbumArt(); 292 if (albumArt == NULL) { 293 LOGE("failed to extract an album art"); 294 return NULL; 295 } 296 size_t size = sizeof(MediaAlbumArt) + albumArt->mSize; 297 mAlbumArtDealer = new MemoryDealer(size); 298 if (mAlbumArtDealer == NULL) { 299 LOGE("failed to create MemoryDealer object"); 300 delete albumArt; 301 return NULL; 302 } 303 mAlbumArt = mAlbumArtDealer->allocate(size); 304 if (mAlbumArt == NULL) { 305 LOGE("not enough memory for MediaAlbumArt size=%u", size); 306 mAlbumArtDealer.clear(); 307 delete albumArt; 308 return NULL; 309 } 310 MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(mAlbumArt->pointer()); 311 albumArtCopy->mSize = albumArt->mSize; 312 albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt); 313 memcpy(albumArtCopy->mData, albumArt->mData, albumArt->mSize); 314 delete albumArt; // Fix memory leakage 315 return mAlbumArt; 316} 317 318const char* MetadataRetrieverClient::extractMetadata(int keyCode) 319{ 320 LOGV("extractMetadata"); 321 Mutex::Autolock lock(mLock); 322 if (mRetriever == NULL) { 323 LOGE("retriever is not initialized"); 324 return NULL; 325 } 326 return mRetriever->extractMetadata(keyCode); 327} 328 329}; // namespace android 330