blob: ba8d9a8eb4edc0f8e24c8c73183519a50f51f939 [file] [log] [blame]
The Android Open Source Project7b5eb022008-12-17 18:05:43 -08001/*
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>
Mathias Agopian75624082009-05-19 19:08:10 -070029#include <binder/MemoryDealer.h>
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080030#include <android_runtime/ActivityManager.h>
Mathias Agopian75624082009-05-19 19:08:10 -070031#include <binder/IPCThreadState.h>
32#include <binder/IServiceManager.h>
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080033#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
Jean-Baptiste Queru6c5b2102009-03-21 11:40:18 -070052#ifndef NO_OPENCORE
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080053 mRetriever = new PVMetadataRetriever();
Jean-Baptiste Queru6c5b2102009-03-21 11:40:18 -070054#else
55 mRetriever = NULL;
56#endif
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080057 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