MetadataRetrieverClient.cpp revision 6c5b21025f746fcb838499ae01b4d384ab1d2f66
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 <utils/MemoryDealer.h> 30#include <android_runtime/ActivityManager.h> 31#include <utils/IPCThreadState.h> 32#include <utils/IServiceManager.h> 33#include <media/MediaMetadataRetrieverInterface.h> 34#include <media/MediaPlayerInterface.h> 35#include <media/PVMetadataRetriever.h> 36#include <private/media/VideoFrame.h> 37 38#include "MetadataRetrieverClient.h" 39 40 41namespace android { 42 43MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid) 44{ 45 LOGV("MetadataRetrieverClient constructor pid(%d)", pid); 46 mPid = pid; 47 mThumbnailDealer = NULL; 48 mAlbumArtDealer = NULL; 49 mThumbnail = NULL; 50 mAlbumArt = NULL; 51 52#ifndef NO_OPENCORE 53 mRetriever = new PVMetadataRetriever(); 54#else 55 mRetriever = NULL; 56#endif 57 if (mRetriever == NULL) { 58 LOGE("failed to initialize the retriever"); 59 } 60} 61 62MetadataRetrieverClient::~MetadataRetrieverClient() 63{ 64 LOGV("MetadataRetrieverClient destructor"); 65 disconnect(); 66} 67 68status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& args) const 69{ 70 const size_t SIZE = 256; 71 char buffer[SIZE]; 72 String8 result; 73 result.append(" MetadataRetrieverClient\n"); 74 snprintf(buffer, 255, " pid(%d)\n", mPid); 75 result.append(buffer); 76 write(fd, result.string(), result.size()); 77 write(fd, "\n", 1); 78 return NO_ERROR; 79} 80 81void MetadataRetrieverClient::disconnect() 82{ 83 LOGV("disconnect from pid %d", mPid); 84 Mutex::Autolock lock(mLock); 85 mRetriever.clear(); 86 mThumbnailDealer.clear(); 87 mAlbumArtDealer.clear(); 88 mThumbnail.clear(); 89 mAlbumArt.clear(); 90 IPCThreadState::self()->flushCommands(); 91} 92 93status_t MetadataRetrieverClient::setDataSource(const char *url) 94{ 95 LOGV("setDataSource(%s)", url); 96 Mutex::Autolock lock(mLock); 97 if (url == NULL) { 98 return UNKNOWN_ERROR; 99 } 100 if (mRetriever == NULL) { 101 LOGE("retriever is not initialized"); 102 return NO_INIT; 103 } 104 return mRetriever->setDataSource(url); 105} 106 107status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length) 108{ 109 LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length); 110 Mutex::Autolock lock(mLock); 111 if (mRetriever == NULL) { 112 LOGE("retriever is not initialized"); 113 ::close(fd); 114 return NO_INIT; 115 } 116 117 struct stat sb; 118 int ret = fstat(fd, &sb); 119 if (ret != 0) { 120 LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno)); 121 return UNKNOWN_ERROR; 122 } 123 LOGV("st_dev = %llu", sb.st_dev); 124 LOGV("st_mode = %u", sb.st_mode); 125 LOGV("st_uid = %lu", sb.st_uid); 126 LOGV("st_gid = %lu", sb.st_gid); 127 LOGV("st_size = %llu", sb.st_size); 128 129 if (offset >= sb.st_size) { 130 LOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size); 131 ::close(fd); 132 return UNKNOWN_ERROR; 133 } 134 if (offset + length > sb.st_size) { 135 length = sb.st_size - offset; 136 LOGE("calculated length = %lld", length); 137 } 138 status_t status = mRetriever->setDataSource(fd, offset, length); 139 ::close(fd); 140 return status; 141} 142 143status_t MetadataRetrieverClient::setMode(int mode) 144{ 145 LOGV("setMode"); 146 Mutex::Autolock lock(mLock); 147 if (mRetriever == NULL) { 148 LOGE("retriever is not initialized"); 149 return NO_INIT; 150 } 151 return mRetriever->setMode(mode); 152} 153 154status_t MetadataRetrieverClient::getMode(int* mode) const 155{ 156 LOGV("getMode"); 157 Mutex::Autolock lock(mLock); 158 if (mRetriever == NULL) { 159 LOGE("retriever is not initialized"); 160 return NO_INIT; 161 } 162 return mRetriever->getMode(mode); 163} 164 165sp<IMemory> MetadataRetrieverClient::captureFrame() 166{ 167 LOGV("captureFrame"); 168 Mutex::Autolock lock(mLock); 169 mThumbnail.clear(); 170 mThumbnailDealer.clear(); 171 if (mRetriever == NULL) { 172 LOGE("retriever is not initialized"); 173 return NULL; 174 } 175 VideoFrame *frame = mRetriever->captureFrame(); 176 if (frame == NULL) { 177 LOGE("failed to capture a video frame"); 178 return NULL; 179 } 180 size_t size = sizeof(VideoFrame) + frame->mSize; 181 mThumbnailDealer = new MemoryDealer(size); 182 if (mThumbnailDealer == NULL) { 183 LOGE("failed to create MemoryDealer"); 184 delete frame; 185 return NULL; 186 } 187 mThumbnail = mThumbnailDealer->allocate(size); 188 if (mThumbnail == NULL) { 189 LOGE("not enough memory for VideoFrame size=%u", size); 190 mThumbnailDealer.clear(); 191 delete frame; 192 return NULL; 193 } 194 VideoFrame *frameCopy = static_cast<VideoFrame *>(mThumbnail->pointer()); 195 frameCopy->mWidth = frame->mWidth; 196 frameCopy->mHeight = frame->mHeight; 197 frameCopy->mDisplayWidth = frame->mDisplayWidth; 198 frameCopy->mDisplayHeight = frame->mDisplayHeight; 199 frameCopy->mSize = frame->mSize; 200 frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame); 201 memcpy(frameCopy->mData, frame->mData, frame->mSize); 202 delete frame; // Fix memory leakage 203 return mThumbnail; 204} 205 206sp<IMemory> MetadataRetrieverClient::extractAlbumArt() 207{ 208 LOGV("extractAlbumArt"); 209 Mutex::Autolock lock(mLock); 210 mAlbumArt.clear(); 211 mAlbumArtDealer.clear(); 212 if (mRetriever == NULL) { 213 LOGE("retriever is not initialized"); 214 return NULL; 215 } 216 MediaAlbumArt *albumArt = mRetriever->extractAlbumArt(); 217 if (albumArt == NULL) { 218 LOGE("failed to extract an album art"); 219 return NULL; 220 } 221 size_t size = sizeof(MediaAlbumArt) + albumArt->mSize; 222 mAlbumArtDealer = new MemoryDealer(size); 223 if (mAlbumArtDealer == NULL) { 224 LOGE("failed to create MemoryDealer object"); 225 delete albumArt; 226 return NULL; 227 } 228 mAlbumArt = mAlbumArtDealer->allocate(size); 229 if (mAlbumArt == NULL) { 230 LOGE("not enough memory for MediaAlbumArt size=%u", size); 231 mAlbumArtDealer.clear(); 232 delete albumArt; 233 return NULL; 234 } 235 MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(mAlbumArt->pointer()); 236 albumArtCopy->mSize = albumArt->mSize; 237 albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt); 238 memcpy(albumArtCopy->mData, albumArt->mData, albumArt->mSize); 239 delete albumArt; // Fix memory leakage 240 return mAlbumArt; 241} 242 243const char* MetadataRetrieverClient::extractMetadata(int keyCode) 244{ 245 LOGV("extractMetadata"); 246 Mutex::Autolock lock(mLock); 247 if (mRetriever == NULL) { 248 LOGE("retriever is not initialized"); 249 return NULL; 250 } 251 return mRetriever->extractMetadata(keyCode); 252} 253 254}; // namespace android 255