• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
3 ** Copyright 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 "MediaMetadataRetriever"
20 
21 #include <binder/IServiceManager.h>
22 #include <binder/IPCThreadState.h>
23 #include <media/mediametadataretriever.h>
24 #include <media/IMediaPlayerService.h>
25 #include <utils/Log.h>
26 #include <dlfcn.h>
27 
28 namespace android {
29 
30 // client singleton for binder interface to service
31 Mutex MediaMetadataRetriever::sServiceLock;
32 sp<IMediaPlayerService> MediaMetadataRetriever::sService;
33 sp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier;
34 
getService()35 const sp<IMediaPlayerService>& MediaMetadataRetriever::getService()
36 {
37     Mutex::Autolock lock(sServiceLock);
38     if (sService == 0) {
39         sp<IServiceManager> sm = defaultServiceManager();
40         sp<IBinder> binder;
41         do {
42             binder = sm->getService(String16("media.player"));
43             if (binder != 0) {
44                 break;
45             }
46             ALOGW("MediaPlayerService not published, waiting...");
47             usleep(500000); // 0.5 s
48         } while (true);
49         if (sDeathNotifier == NULL) {
50             sDeathNotifier = new DeathNotifier();
51         }
52         binder->linkToDeath(sDeathNotifier);
53         sService = interface_cast<IMediaPlayerService>(binder);
54     }
55     ALOGE_IF(sService == 0, "no MediaPlayerService!?");
56     return sService;
57 }
58 
MediaMetadataRetriever()59 MediaMetadataRetriever::MediaMetadataRetriever()
60 {
61     ALOGV("constructor");
62     const sp<IMediaPlayerService>& service(getService());
63     if (service == 0) {
64         ALOGE("failed to obtain MediaMetadataRetrieverService");
65         return;
66     }
67     sp<IMediaMetadataRetriever> retriever(service->createMetadataRetriever(getpid()));
68     if (retriever == 0) {
69         ALOGE("failed to create IMediaMetadataRetriever object from server");
70     }
71     mRetriever = retriever;
72 }
73 
~MediaMetadataRetriever()74 MediaMetadataRetriever::~MediaMetadataRetriever()
75 {
76     ALOGV("destructor");
77     disconnect();
78     IPCThreadState::self()->flushCommands();
79 }
80 
disconnect()81 void MediaMetadataRetriever::disconnect()
82 {
83     ALOGV("disconnect");
84     sp<IMediaMetadataRetriever> retriever;
85     {
86         Mutex::Autolock _l(mLock);
87         retriever = mRetriever;
88         mRetriever.clear();
89     }
90     if (retriever != 0) {
91         retriever->disconnect();
92     }
93 }
94 
setDataSource(const char * srcUrl,const KeyedVector<String8,String8> * headers)95 status_t MediaMetadataRetriever::setDataSource(
96         const char *srcUrl, const KeyedVector<String8, String8> *headers)
97 {
98     ALOGV("setDataSource");
99     Mutex::Autolock _l(mLock);
100     if (mRetriever == 0) {
101         ALOGE("retriever is not initialized");
102         return INVALID_OPERATION;
103     }
104     if (srcUrl == NULL) {
105         ALOGE("data source is a null pointer");
106         return UNKNOWN_ERROR;
107     }
108     ALOGV("data source (%s)", srcUrl);
109     return mRetriever->setDataSource(srcUrl, headers);
110 }
111 
setDataSource(int fd,int64_t offset,int64_t length)112 status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
113 {
114     ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
115     Mutex::Autolock _l(mLock);
116     if (mRetriever == 0) {
117         ALOGE("retriever is not initialized");
118         return INVALID_OPERATION;
119     }
120     if (fd < 0 || offset < 0 || length < 0) {
121         ALOGE("Invalid negative argument");
122         return UNKNOWN_ERROR;
123     }
124     return mRetriever->setDataSource(fd, offset, length);
125 }
126 
getFrameAtTime(int64_t timeUs,int option)127 sp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option)
128 {
129     ALOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
130     Mutex::Autolock _l(mLock);
131     if (mRetriever == 0) {
132         ALOGE("retriever is not initialized");
133         return NULL;
134     }
135     return mRetriever->getFrameAtTime(timeUs, option);
136 }
137 
extractMetadata(int keyCode)138 const char* MediaMetadataRetriever::extractMetadata(int keyCode)
139 {
140     ALOGV("extractMetadata(%d)", keyCode);
141     Mutex::Autolock _l(mLock);
142     if (mRetriever == 0) {
143         ALOGE("retriever is not initialized");
144         return NULL;
145     }
146     return mRetriever->extractMetadata(keyCode);
147 }
148 
extractAlbumArt()149 sp<IMemory> MediaMetadataRetriever::extractAlbumArt()
150 {
151     ALOGV("extractAlbumArt");
152     Mutex::Autolock _l(mLock);
153     if (mRetriever == 0) {
154         ALOGE("retriever is not initialized");
155         return NULL;
156     }
157     return mRetriever->extractAlbumArt();
158 }
159 
binderDied(const wp<IBinder> & who)160 void MediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>& who) {
161     Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock);
162     MediaMetadataRetriever::sService.clear();
163     ALOGW("MediaMetadataRetriever server died!");
164 }
165 
~DeathNotifier()166 MediaMetadataRetriever::DeathNotifier::~DeathNotifier()
167 {
168     Mutex::Autolock lock(sServiceLock);
169     if (sService != 0) {
170         sService->asBinder()->unlinkToDeath(this);
171     }
172 }
173 
174 }; // namespace android
175