Home | History | Annotate | Download | only in libmedia
      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 
     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 
     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());
     68     if (retriever == 0) {
     69         ALOGE("failed to create IMediaMetadataRetriever object from server");
     70     }
     71     mRetriever = retriever;
     72 }
     73 
     74 MediaMetadataRetriever::~MediaMetadataRetriever()
     75 {
     76     ALOGV("destructor");
     77     disconnect();
     78     IPCThreadState::self()->flushCommands();
     79 }
     80 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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