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