189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/*
289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2008, The Android Open Source Project
489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License.
789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at
889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and
1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License.
1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/
1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0
1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "MediaMetadataRetriever"
2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn#include <inttypes.h>
2234fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn
237562408b2261d38415453378b6188f74fda99d88Mathias Agopian#include <binder/IServiceManager.h>
247562408b2261d38415453378b6188f74fda99d88Mathias Agopian#include <binder/IPCThreadState.h>
2589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/mediametadataretriever.h>
261b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h>
2789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/IMediaPlayerService.h>
2889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h>
2989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <dlfcn.h>
3089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android {
3289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// client singleton for binder interface to service
3489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMutex MediaMetadataRetriever::sServiceLock;
3589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectsp<IMediaPlayerService> MediaMetadataRetriever::sService;
3689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectsp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier;
3789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3861a6d26aab95870279b274e565c1495748befde0Marco Nelissenconst sp<IMediaPlayerService> MediaMetadataRetriever::getService()
3989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
4089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(sServiceLock);
417fc9a6fdf146ded90b51c52f4a05d797294dcb85Glenn Kasten    if (sService == 0) {
4289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        sp<IServiceManager> sm = defaultServiceManager();
4389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        sp<IBinder> binder;
4489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        do {
4589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            binder = sm->getService(String16("media.player"));
4689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (binder != 0) {
4789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
4889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
495ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("MediaPlayerService not published, waiting...");
5089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            usleep(500000); // 0.5 s
51e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten        } while (true);
5289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (sDeathNotifier == NULL) {
5389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            sDeathNotifier = new DeathNotifier();
5489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
5589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        binder->linkToDeath(sDeathNotifier);
5689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        sService = interface_cast<IMediaPlayerService>(binder);
5789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
5829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    ALOGE_IF(sService == 0, "no MediaPlayerService!?");
5989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return sService;
6089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
6189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMediaMetadataRetriever::MediaMetadataRetriever()
6389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("constructor");
6561a6d26aab95870279b274e565c1495748befde0Marco Nelissen    const sp<IMediaPlayerService> service(getService());
6689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (service == 0) {
6729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to obtain MediaMetadataRetrieverService");
6889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return;
6989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
708d6cc842e8d525405c68e57fdf3bc5da0b4d7e87Glenn Kasten    sp<IMediaMetadataRetriever> retriever(service->createMetadataRetriever());
7189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (retriever == 0) {
7229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("failed to create IMediaMetadataRetriever object from server");
7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mRetriever = retriever;
7589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
7689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMediaMetadataRetriever::~MediaMetadataRetriever()
7889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("destructor");
8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    disconnect();
8189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    IPCThreadState::self()->flushCommands();
8289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
8389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid MediaMetadataRetriever::disconnect()
8589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("disconnect");
8789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    sp<IMediaMetadataRetriever> retriever;
8889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    {
8989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        Mutex::Autolock _l(mLock);
9089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        retriever = mRetriever;
9189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mRetriever.clear();
9289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
9389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (retriever != 0) {
9489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        retriever->disconnect();
9589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
9689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
9789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
98af8791e112c8072452bd14ef3c43a47511d19542Andreas Huberstatus_t MediaMetadataRetriever::setDataSource(
991b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<IMediaHTTPService> &httpService,
1001b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const char *srcUrl,
1011b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const KeyedVector<String8, String8> *headers)
10289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
1033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDataSource");
104a17a1347ffe281fc70633ba8dc98f6cf49ac06ffDave Sparks    Mutex::Autolock _l(mLock);
10589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mRetriever == 0) {
10629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("retriever is not initialized");
10789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
10889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
10989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (srcUrl == NULL) {
11029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("data source is a null pointer");
11189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return UNKNOWN_ERROR;
11289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
1133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("data source (%s)", srcUrl);
1141b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return mRetriever->setDataSource(httpService, srcUrl, headers);
11589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
11689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
11789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
11889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
11934fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn    ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
120a17a1347ffe281fc70633ba8dc98f6cf49ac06ffDave Sparks    Mutex::Autolock _l(mLock);
12189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mRetriever == 0) {
12229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("retriever is not initialized");
12389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
12489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
12589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (fd < 0 || offset < 0 || length < 0) {
12629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid negative argument");
12789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return UNKNOWN_ERROR;
12889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
12989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mRetriever->setDataSource(fd, offset, length);
13089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
13189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
13299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsstatus_t MediaMetadataRetriever::setDataSource(
13399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins    const sp<IDataSource>& dataSource)
13499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins{
13599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins    ALOGV("setDataSource(IDataSource)");
13699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins    Mutex::Autolock _l(mLock);
13799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins    if (mRetriever == 0) {
13899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins        ALOGE("retriever is not initialized");
13999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins        return INVALID_OPERATION;
14099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins    }
14199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins    return mRetriever->setDataSource(dataSource);
14299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins}
14399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins
14416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dongsp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option)
14589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
14634fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn    ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d)", timeUs, option);
147a17a1347ffe281fc70633ba8dc98f6cf49ac06ffDave Sparks    Mutex::Autolock _l(mLock);
14889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mRetriever == 0) {
14929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("retriever is not initialized");
15089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return NULL;
15189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
15216afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong    return mRetriever->getFrameAtTime(timeUs, option);
15389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
15489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
15589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectconst char* MediaMetadataRetriever::extractMetadata(int keyCode)
15689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
1573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("extractMetadata(%d)", keyCode);
158a17a1347ffe281fc70633ba8dc98f6cf49ac06ffDave Sparks    Mutex::Autolock _l(mLock);
15989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mRetriever == 0) {
16029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("retriever is not initialized");
16189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return NULL;
16289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
16389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mRetriever->extractMetadata(keyCode);
16489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
16589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
16689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectsp<IMemory> MediaMetadataRetriever::extractAlbumArt()
16789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
1683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("extractAlbumArt");
169a17a1347ffe281fc70633ba8dc98f6cf49ac06ffDave Sparks    Mutex::Autolock _l(mLock);
17089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mRetriever == 0) {
17129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("retriever is not initialized");
17289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return NULL;
17389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
17489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mRetriever->extractAlbumArt();
17589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
17689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1777c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastenvoid MediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>& who __unused) {
17889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock);
17989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    MediaMetadataRetriever::sService.clear();
1805ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block    ALOGW("MediaMetadataRetriever server died!");
18189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
18289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
18389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMediaMetadataRetriever::DeathNotifier::~DeathNotifier()
18489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
18589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(sServiceLock);
18689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (sService != 0) {
18706b46062d2f8bc82ca3061a23d197734ae51918bMarco Nelissen        IInterface::asBinder(sService)->unlinkToDeath(this);
18889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
18989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
19089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
19140bc906252974d0b389ae4a147232d0c9a97193fGlenn Kasten} // namespace android
192