MetadataRetrieverClient.cpp revision 7b5eb023f8d87cca6d830ae6c11c6aadbe02aca8
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 mRetriever = new PVMetadataRetriever(); 53 if (mRetriever == NULL) { 54 LOGE("failed to initialize the retriever"); 55 } 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)\n", mPid); 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 IPCThreadState::self()->flushCommands(); 87} 88 89status_t MetadataRetrieverClient::setDataSource(const char *url) 90{ 91 LOGV("setDataSource(%s)", url); 92 Mutex::Autolock lock(mLock); 93 if (url == NULL) { 94 return UNKNOWN_ERROR; 95 } 96 if (mRetriever == NULL) { 97 LOGE("retriever is not initialized"); 98 return NO_INIT; 99 } 100 return mRetriever->setDataSource(url); 101} 102 103status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length) 104{ 105 LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length); 106 Mutex::Autolock lock(mLock); 107 if (mRetriever == NULL) { 108 LOGE("retriever is not initialized"); 109 ::close(fd); 110 return NO_INIT; 111 } 112 113 struct stat sb; 114 int ret = fstat(fd, &sb); 115 if (ret != 0) { 116 LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno)); 117 return UNKNOWN_ERROR; 118 } 119 LOGV("st_dev = %llu", sb.st_dev); 120 LOGV("st_mode = %u", sb.st_mode); 121 LOGV("st_uid = %lu", sb.st_uid); 122 LOGV("st_gid = %lu", sb.st_gid); 123 LOGV("st_size = %llu", sb.st_size); 124 125 if (offset >= sb.st_size) { 126 LOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size); 127 ::close(fd); 128 return UNKNOWN_ERROR; 129 } 130 if (offset + length > sb.st_size) { 131 length = sb.st_size - offset; 132 LOGE("calculated length = %lld", length); 133 } 134 status_t status = mRetriever->setDataSource(fd, offset, length); 135 ::close(fd); 136 return status; 137} 138 139status_t MetadataRetrieverClient::setMode(int mode) 140{ 141 LOGV("setMode"); 142 Mutex::Autolock lock(mLock); 143 if (mRetriever == NULL) { 144 LOGE("retriever is not initialized"); 145 return NO_INIT; 146 } 147 return mRetriever->setMode(mode); 148} 149 150status_t MetadataRetrieverClient::getMode(int* mode) const 151{ 152 LOGV("getMode"); 153 Mutex::Autolock lock(mLock); 154 if (mRetriever == NULL) { 155 LOGE("retriever is not initialized"); 156 return NO_INIT; 157 } 158 return mRetriever->getMode(mode); 159} 160 161sp<IMemory> MetadataRetrieverClient::captureFrame() 162{ 163 LOGV("captureFrame"); 164 Mutex::Autolock lock(mLock); 165 mThumbnail.clear(); 166 mThumbnailDealer.clear(); 167 if (mRetriever == NULL) { 168 LOGE("retriever is not initialized"); 169 return NULL; 170 } 171 VideoFrame *frame = mRetriever->captureFrame(); 172 if (frame == NULL) { 173 LOGE("failed to capture a video frame"); 174 return NULL; 175 } 176 size_t size = sizeof(VideoFrame) + frame->mSize; 177 mThumbnailDealer = new MemoryDealer(size); 178 if (mThumbnailDealer == NULL) { 179 LOGE("failed to create MemoryDealer"); 180 delete frame; 181 return NULL; 182 } 183 mThumbnail = mThumbnailDealer->allocate(size); 184 if (mThumbnail == NULL) { 185 LOGE("not enough memory for VideoFrame size=%u", size); 186 mThumbnailDealer.clear(); 187 delete frame; 188 return NULL; 189 } 190 VideoFrame *frameCopy = static_cast<VideoFrame *>(mThumbnail->pointer()); 191 frameCopy->mWidth = frame->mWidth; 192 frameCopy->mHeight = frame->mHeight; 193 frameCopy->mDisplayWidth = frame->mDisplayWidth; 194 frameCopy->mDisplayHeight = frame->mDisplayHeight; 195 frameCopy->mSize = frame->mSize; 196 frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame); 197 memcpy(frameCopy->mData, frame->mData, frame->mSize); 198 delete frame; // Fix memory leakage 199 return mThumbnail; 200} 201 202sp<IMemory> MetadataRetrieverClient::extractAlbumArt() 203{ 204 LOGV("extractAlbumArt"); 205 Mutex::Autolock lock(mLock); 206 mAlbumArt.clear(); 207 mAlbumArtDealer.clear(); 208 if (mRetriever == NULL) { 209 LOGE("retriever is not initialized"); 210 return NULL; 211 } 212 MediaAlbumArt *albumArt = mRetriever->extractAlbumArt(); 213 if (albumArt == NULL) { 214 LOGE("failed to extract an album art"); 215 return NULL; 216 } 217 size_t size = sizeof(MediaAlbumArt) + albumArt->mSize; 218 mAlbumArtDealer = new MemoryDealer(size); 219 if (mAlbumArtDealer == NULL) { 220 LOGE("failed to create MemoryDealer object"); 221 delete albumArt; 222 return NULL; 223 } 224 mAlbumArt = mAlbumArtDealer->allocate(size); 225 if (mAlbumArt == NULL) { 226 LOGE("not enough memory for MediaAlbumArt size=%u", size); 227 mAlbumArtDealer.clear(); 228 delete albumArt; 229 return NULL; 230 } 231 MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(mAlbumArt->pointer()); 232 albumArtCopy->mSize = albumArt->mSize; 233 albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt); 234 memcpy(albumArtCopy->mData, albumArt->mData, albumArt->mSize); 235 delete albumArt; // Fix memory leakage 236 return mAlbumArt; 237} 238 239const char* MetadataRetrieverClient::extractMetadata(int keyCode) 240{ 241 LOGV("extractMetadata"); 242 Mutex::Autolock lock(mLock); 243 if (mRetriever == NULL) { 244 LOGE("retriever is not initialized"); 245 return NULL; 246 } 247 return mRetriever->extractMetadata(keyCode); 248} 249 250}; // namespace android 251