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