Home | History | Annotate | Download | only in libmediaplayerservice
      1 /*
      2 **
      3 ** Copyright (C) 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 "MetadataRetrieverClient"
     20 #include <utils/Log.h>
     21 
     22 #include <sys/types.h>
     23 #include <sys/stat.h>
     24 #include <sys/resource.h>
     25 #include <dirent.h>
     26 #include <unistd.h>
     27 
     28 #include <string.h>
     29 #include <cutils/atomic.h>
     30 #include <cutils/properties.h>
     31 #include <binder/MemoryBase.h>
     32 #include <binder/MemoryHeapBase.h>
     33 #include <android_runtime/ActivityManager.h>
     34 #include <binder/IPCThreadState.h>
     35 #include <binder/IServiceManager.h>
     36 #include <media/MediaMetadataRetrieverInterface.h>
     37 #include <media/MediaPlayerInterface.h>
     38 #include <media/PVMetadataRetriever.h>
     39 #include <private/media/VideoFrame.h>
     40 #include "MidiMetadataRetriever.h"
     41 #include "MetadataRetrieverClient.h"
     42 #include "StagefrightMetadataRetriever.h"
     43 
     44 /* desktop Linux needs a little help with gettid() */
     45 #if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
     46 #define __KERNEL__
     47 # include <linux/unistd.h>
     48 #ifdef _syscall0
     49 _syscall0(pid_t,gettid)
     50 #else
     51 pid_t gettid() { return syscall(__NR_gettid);}
     52 #endif
     53 #undef __KERNEL__
     54 #endif
     55 
     56 namespace android {
     57 
     58 extern player_type getPlayerType(const char* url);
     59 extern player_type getPlayerType(int fd, int64_t offset, int64_t length);
     60 
     61 MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid)
     62 {
     63     LOGV("MetadataRetrieverClient constructor pid(%d)", pid);
     64     mPid = pid;
     65     mThumbnail = NULL;
     66     mAlbumArt = NULL;
     67     mRetriever = NULL;
     68 }
     69 
     70 MetadataRetrieverClient::~MetadataRetrieverClient()
     71 {
     72     LOGV("MetadataRetrieverClient destructor");
     73     disconnect();
     74 }
     75 
     76 status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& args) const
     77 {
     78     const size_t SIZE = 256;
     79     char buffer[SIZE];
     80     String8 result;
     81     result.append(" MetadataRetrieverClient\n");
     82     snprintf(buffer, 255, "  pid(%d)\n", mPid);
     83     result.append(buffer);
     84     write(fd, result.string(), result.size());
     85     write(fd, "\n", 1);
     86     return NO_ERROR;
     87 }
     88 
     89 void MetadataRetrieverClient::disconnect()
     90 {
     91     LOGV("disconnect from pid %d", mPid);
     92     Mutex::Autolock lock(mLock);
     93     mRetriever.clear();
     94     mThumbnail.clear();
     95     mAlbumArt.clear();
     96     IPCThreadState::self()->flushCommands();
     97 }
     98 
     99 static sp<MediaMetadataRetrieverBase> createRetriever(player_type playerType)
    100 {
    101     sp<MediaMetadataRetrieverBase> p;
    102     switch (playerType) {
    103         case STAGEFRIGHT_PLAYER:
    104         {
    105             p = new StagefrightMetadataRetriever;
    106             break;
    107         }
    108 #ifndef NO_OPENCORE
    109         case PV_PLAYER:
    110             LOGV("create pv metadata retriever");
    111             p = new PVMetadataRetriever();
    112             break;
    113 #endif
    114         case SONIVOX_PLAYER:
    115             LOGV("create midi metadata retriever");
    116             p = new MidiMetadataRetriever();
    117             break;
    118         default:
    119             // TODO:
    120             // support for TEST_PLAYER
    121             LOGE("player type %d is not supported",  playerType);
    122             break;
    123     }
    124     if (p == NULL) {
    125         LOGE("failed to create a retriever object");
    126     }
    127     return p;
    128 }
    129 
    130 status_t MetadataRetrieverClient::setDataSource(const char *url)
    131 {
    132     LOGV("setDataSource(%s)", url);
    133     Mutex::Autolock lock(mLock);
    134     if (url == NULL) {
    135         return UNKNOWN_ERROR;
    136     }
    137     player_type playerType = getPlayerType(url);
    138     LOGV("player type = %d", playerType);
    139     sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
    140     if (p == NULL) return NO_INIT;
    141     status_t ret = p->setDataSource(url);
    142     if (ret == NO_ERROR) mRetriever = p;
    143     return ret;
    144 }
    145 
    146 status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length)
    147 {
    148     LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
    149     Mutex::Autolock lock(mLock);
    150     struct stat sb;
    151     int ret = fstat(fd, &sb);
    152     if (ret != 0) {
    153         LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
    154         return BAD_VALUE;
    155     }
    156     LOGV("st_dev  = %llu", sb.st_dev);
    157     LOGV("st_mode = %u", sb.st_mode);
    158     LOGV("st_uid  = %lu", sb.st_uid);
    159     LOGV("st_gid  = %lu", sb.st_gid);
    160     LOGV("st_size = %llu", sb.st_size);
    161 
    162     if (offset >= sb.st_size) {
    163         LOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size);
    164         ::close(fd);
    165         return BAD_VALUE;
    166     }
    167     if (offset + length > sb.st_size) {
    168         length = sb.st_size - offset;
    169         LOGV("calculated length = %lld", length);
    170     }
    171 
    172     player_type playerType = getPlayerType(fd, offset, length);
    173     LOGV("player type = %d", playerType);
    174     sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
    175     if (p == NULL) {
    176         ::close(fd);
    177         return NO_INIT;
    178     }
    179     status_t status = p->setDataSource(fd, offset, length);
    180     if (status == NO_ERROR) mRetriever = p;
    181     ::close(fd);
    182     return status;
    183 }
    184 
    185 sp<IMemory> MetadataRetrieverClient::getFrameAtTime(int64_t timeUs, int option)
    186 {
    187     LOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
    188     Mutex::Autolock lock(mLock);
    189     mThumbnail.clear();
    190     if (mRetriever == NULL) {
    191         LOGE("retriever is not initialized");
    192         return NULL;
    193     }
    194     VideoFrame *frame = mRetriever->getFrameAtTime(timeUs, option);
    195     if (frame == NULL) {
    196         LOGE("failed to capture a video frame");
    197         return NULL;
    198     }
    199     size_t size = sizeof(VideoFrame) + frame->mSize;
    200     sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
    201     if (heap == NULL) {
    202         LOGE("failed to create MemoryDealer");
    203         delete frame;
    204         return NULL;
    205     }
    206     mThumbnail = new MemoryBase(heap, 0, size);
    207     if (mThumbnail == NULL) {
    208         LOGE("not enough memory for VideoFrame size=%u", size);
    209         delete frame;
    210         return NULL;
    211     }
    212     VideoFrame *frameCopy = static_cast<VideoFrame *>(mThumbnail->pointer());
    213     frameCopy->mWidth = frame->mWidth;
    214     frameCopy->mHeight = frame->mHeight;
    215     frameCopy->mDisplayWidth = frame->mDisplayWidth;
    216     frameCopy->mDisplayHeight = frame->mDisplayHeight;
    217     frameCopy->mSize = frame->mSize;
    218     frameCopy->mRotationAngle = frame->mRotationAngle;
    219     LOGV("rotation: %d", frameCopy->mRotationAngle);
    220     frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);
    221     memcpy(frameCopy->mData, frame->mData, frame->mSize);
    222     delete frame;  // Fix memory leakage
    223     return mThumbnail;
    224 }
    225 
    226 sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
    227 {
    228     LOGV("extractAlbumArt");
    229     Mutex::Autolock lock(mLock);
    230     mAlbumArt.clear();
    231     if (mRetriever == NULL) {
    232         LOGE("retriever is not initialized");
    233         return NULL;
    234     }
    235     MediaAlbumArt *albumArt = mRetriever->extractAlbumArt();
    236     if (albumArt == NULL) {
    237         LOGE("failed to extract an album art");
    238         return NULL;
    239     }
    240     size_t size = sizeof(MediaAlbumArt) + albumArt->mSize;
    241     sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
    242     if (heap == NULL) {
    243         LOGE("failed to create MemoryDealer object");
    244         delete albumArt;
    245         return NULL;
    246     }
    247     mAlbumArt = new MemoryBase(heap, 0, size);
    248     if (mAlbumArt == NULL) {
    249         LOGE("not enough memory for MediaAlbumArt size=%u", size);
    250         delete albumArt;
    251         return NULL;
    252     }
    253     MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(mAlbumArt->pointer());
    254     albumArtCopy->mSize = albumArt->mSize;
    255     albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt);
    256     memcpy(albumArtCopy->mData, albumArt->mData, albumArt->mSize);
    257     delete albumArt;  // Fix memory leakage
    258     return mAlbumArt;
    259 }
    260 
    261 const char* MetadataRetrieverClient::extractMetadata(int keyCode)
    262 {
    263     LOGV("extractMetadata");
    264     Mutex::Autolock lock(mLock);
    265     if (mRetriever == NULL) {
    266         LOGE("retriever is not initialized");
    267         return NULL;
    268     }
    269     return mRetriever->extractMetadata(keyCode);
    270 }
    271 
    272 }; // namespace android
    273