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.get() == 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             LOGW("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     LOGE_IF(sService == 0, "no MediaPlayerService!?");
     56     return sService;
     57 }
     58 
     59 MediaMetadataRetriever::MediaMetadataRetriever()
     60 {
     61     LOGV("constructor");
     62     const sp<IMediaPlayerService>& service(getService());
     63     if (service == 0) {
     64         LOGE("failed to obtain MediaMetadataRetrieverService");
     65         return;
     66     }
     67     sp<IMediaMetadataRetriever> retriever(service->createMetadataRetriever(getpid()));
     68     if (retriever == 0) {
     69         LOGE("failed to create IMediaMetadataRetriever object from server");
     70     }
     71     mRetriever = retriever;
     72 }
     73 
     74 MediaMetadataRetriever::~MediaMetadataRetriever()
     75 {
     76     LOGV("destructor");
     77     disconnect();
     78     IPCThreadState::self()->flushCommands();
     79 }
     80 
     81 void MediaMetadataRetriever::disconnect()
     82 {
     83     LOGV("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(const char* srcUrl)
     96 {
     97     LOGV("setDataSource");
     98     Mutex::Autolock _l(mLock);
     99     if (mRetriever == 0) {
    100         LOGE("retriever is not initialized");
    101         return INVALID_OPERATION;
    102     }
    103     if (srcUrl == NULL) {
    104         LOGE("data source is a null pointer");
    105         return UNKNOWN_ERROR;
    106     }
    107     LOGV("data source (%s)", srcUrl);
    108     return mRetriever->setDataSource(srcUrl);
    109 }
    110 
    111 status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
    112 {
    113     LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
    114     Mutex::Autolock _l(mLock);
    115     if (mRetriever == 0) {
    116         LOGE("retriever is not initialized");
    117         return INVALID_OPERATION;
    118     }
    119     if (fd < 0 || offset < 0 || length < 0) {
    120         LOGE("Invalid negative argument");
    121         return UNKNOWN_ERROR;
    122     }
    123     return mRetriever->setDataSource(fd, offset, length);
    124 }
    125 
    126 status_t MediaMetadataRetriever::setMode(int mode)
    127 {
    128     LOGV("setMode(%d)", mode);
    129     Mutex::Autolock _l(mLock);
    130     if (mRetriever == 0) {
    131         LOGE("retriever is not initialized");
    132         return INVALID_OPERATION;
    133     }
    134     return mRetriever->setMode(mode);
    135 }
    136 
    137 status_t MediaMetadataRetriever::getMode(int* mode)
    138 {
    139     LOGV("getMode");
    140     Mutex::Autolock _l(mLock);
    141     if (mRetriever == 0) {
    142         LOGE("retriever is not initialized");
    143         return INVALID_OPERATION;
    144     }
    145     return mRetriever->getMode(mode);
    146 }
    147 
    148 sp<IMemory> MediaMetadataRetriever::captureFrame()
    149 {
    150     LOGV("captureFrame");
    151     Mutex::Autolock _l(mLock);
    152     if (mRetriever == 0) {
    153         LOGE("retriever is not initialized");
    154         return NULL;
    155     }
    156     return mRetriever->captureFrame();
    157 }
    158 
    159 const char* MediaMetadataRetriever::extractMetadata(int keyCode)
    160 {
    161     LOGV("extractMetadata(%d)", keyCode);
    162     Mutex::Autolock _l(mLock);
    163     if (mRetriever == 0) {
    164         LOGE("retriever is not initialized");
    165         return NULL;
    166     }
    167     return mRetriever->extractMetadata(keyCode);
    168 }
    169 
    170 sp<IMemory> MediaMetadataRetriever::extractAlbumArt()
    171 {
    172     LOGV("extractAlbumArt");
    173     Mutex::Autolock _l(mLock);
    174     if (mRetriever == 0) {
    175         LOGE("retriever is not initialized");
    176         return NULL;
    177     }
    178     return mRetriever->extractAlbumArt();
    179 }
    180 
    181 void MediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>& who) {
    182     Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock);
    183     MediaMetadataRetriever::sService.clear();
    184     LOGW("MediaMetadataRetriever server died!");
    185 }
    186 
    187 MediaMetadataRetriever::DeathNotifier::~DeathNotifier()
    188 {
    189     Mutex::Autolock lock(sServiceLock);
    190     if (sService != 0) {
    191         sService->asBinder()->unlinkToDeath(this);
    192     }
    193 }
    194 
    195 }; // namespace android
    196