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