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