Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 //#define LOG_NDEBUG 0
     17 #define LOG_TAG "DataSource"
     18 
     19 #include "include/CallbackDataSource.h"
     20 #include "include/HTTPBase.h"
     21 #include "include/NuCachedSource2.h"
     22 
     23 #include <media/IDataSource.h>
     24 #include <media/IMediaHTTPConnection.h>
     25 #include <media/IMediaHTTPService.h>
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/foundation/AMessage.h>
     28 #include <media/stagefright/DataSource.h>
     29 #include <media/stagefright/DataURISource.h>
     30 #include <media/stagefright/FileSource.h>
     31 #include <media/stagefright/MediaErrors.h>
     32 #include <media/stagefright/MediaHTTP.h>
     33 #include <media/stagefright/RemoteDataSource.h>
     34 #include <media/stagefright/Utils.h>
     35 #include <utils/String8.h>
     36 
     37 #include <cutils/properties.h>
     38 
     39 #include <private/android_filesystem_config.h>
     40 
     41 namespace android {
     42 
     43 bool DataSource::getUInt16(off64_t offset, uint16_t *x) {
     44     *x = 0;
     45 
     46     uint8_t byte[2];
     47     if (readAt(offset, byte, 2) != 2) {
     48         return false;
     49     }
     50 
     51     *x = (byte[0] << 8) | byte[1];
     52 
     53     return true;
     54 }
     55 
     56 bool DataSource::getUInt24(off64_t offset, uint32_t *x) {
     57     *x = 0;
     58 
     59     uint8_t byte[3];
     60     if (readAt(offset, byte, 3) != 3) {
     61         return false;
     62     }
     63 
     64     *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];
     65 
     66     return true;
     67 }
     68 
     69 bool DataSource::getUInt32(off64_t offset, uint32_t *x) {
     70     *x = 0;
     71 
     72     uint32_t tmp;
     73     if (readAt(offset, &tmp, 4) != 4) {
     74         return false;
     75     }
     76 
     77     *x = ntohl(tmp);
     78 
     79     return true;
     80 }
     81 
     82 bool DataSource::getUInt64(off64_t offset, uint64_t *x) {
     83     *x = 0;
     84 
     85     uint64_t tmp;
     86     if (readAt(offset, &tmp, 8) != 8) {
     87         return false;
     88     }
     89 
     90     *x = ntoh64(tmp);
     91 
     92     return true;
     93 }
     94 
     95 bool DataSource::getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
     96     if (size == 2) {
     97         return getUInt16(offset, x);
     98     }
     99     if (size == 1) {
    100         uint8_t tmp;
    101         if (readAt(offset, &tmp, 1) == 1) {
    102             *x = tmp;
    103             return true;
    104         }
    105     }
    106     return false;
    107 }
    108 
    109 bool DataSource::getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
    110     if (size == 4) {
    111         return getUInt32(offset, x);
    112     }
    113     if (size == 2) {
    114         uint16_t tmp;
    115         if (getUInt16(offset, &tmp)) {
    116             *x = tmp;
    117             return true;
    118         }
    119     }
    120     return false;
    121 }
    122 
    123 bool DataSource::getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
    124     if (size == 8) {
    125         return getUInt64(offset, x);
    126     }
    127     if (size == 4) {
    128         uint32_t tmp;
    129         if (getUInt32(offset, &tmp)) {
    130             *x = tmp;
    131             return true;
    132         }
    133     }
    134     return false;
    135 }
    136 
    137 status_t DataSource::getSize(off64_t *size) {
    138     *size = 0;
    139 
    140     return ERROR_UNSUPPORTED;
    141 }
    142 
    143 sp<IDataSource> DataSource::getIDataSource() const {
    144     return nullptr;
    145 }
    146 
    147 ////////////////////////////////////////////////////////////////////////////////
    148 
    149 // static
    150 sp<DataSource> DataSource::CreateFromURI(
    151         const sp<IMediaHTTPService> &httpService,
    152         const char *uri,
    153         const KeyedVector<String8, String8> *headers,
    154         String8 *contentType,
    155         HTTPBase *httpSource) {
    156     if (contentType != NULL) {
    157         *contentType = "";
    158     }
    159 
    160     sp<DataSource> source;
    161     if (!strncasecmp("file://", uri, 7)) {
    162         source = new FileSource(uri + 7);
    163     } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
    164         if (httpService == NULL) {
    165             ALOGE("Invalid http service!");
    166             return NULL;
    167         }
    168 
    169         if (httpSource == NULL) {
    170             sp<IMediaHTTPConnection> conn = httpService->makeHTTPConnection();
    171             if (conn == NULL) {
    172                 ALOGE("Failed to make http connection from http service!");
    173                 return NULL;
    174             }
    175             httpSource = new MediaHTTP(conn);
    176         }
    177 
    178         String8 cacheConfig;
    179         bool disconnectAtHighwatermark = false;
    180         KeyedVector<String8, String8> nonCacheSpecificHeaders;
    181         if (headers != NULL) {
    182             nonCacheSpecificHeaders = *headers;
    183             NuCachedSource2::RemoveCacheSpecificHeaders(
    184                     &nonCacheSpecificHeaders,
    185                     &cacheConfig,
    186                     &disconnectAtHighwatermark);
    187         }
    188 
    189         if (httpSource->connect(uri, &nonCacheSpecificHeaders) != OK) {
    190             ALOGE("Failed to connect http source!");
    191             return NULL;
    192         }
    193 
    194         if (contentType != NULL) {
    195             *contentType = httpSource->getMIMEType();
    196         }
    197 
    198         source = NuCachedSource2::Create(
    199                 httpSource,
    200                 cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
    201                 disconnectAtHighwatermark);
    202     } else if (!strncasecmp("data:", uri, 5)) {
    203         source = DataURISource::Create(uri);
    204     } else {
    205         // Assume it's a filename.
    206         source = new FileSource(uri);
    207     }
    208 
    209     if (source == NULL || source->initCheck() != OK) {
    210         return NULL;
    211     }
    212 
    213     return source;
    214 }
    215 
    216 sp<DataSource> DataSource::CreateFromFd(int fd, int64_t offset, int64_t length) {
    217     sp<FileSource> source = new FileSource(fd, offset, length);
    218     return source->initCheck() != OK ? nullptr : source;
    219 }
    220 
    221 sp<DataSource> DataSource::CreateMediaHTTP(const sp<IMediaHTTPService> &httpService) {
    222     if (httpService == NULL) {
    223         return NULL;
    224     }
    225 
    226     sp<IMediaHTTPConnection> conn = httpService->makeHTTPConnection();
    227     if (conn == NULL) {
    228         return NULL;
    229     } else {
    230         return new MediaHTTP(conn);
    231     }
    232 }
    233 
    234 sp<DataSource> DataSource::CreateFromIDataSource(const sp<IDataSource> &source) {
    235     return new TinyCacheSource(new CallbackDataSource(source));
    236 }
    237 
    238 String8 DataSource::getMIMEType() const {
    239     return String8("application/octet-stream");
    240 }
    241 
    242 sp<IDataSource> DataSource::asIDataSource() {
    243     return RemoteDataSource::wrap(sp<DataSource>(this));
    244 }
    245 
    246 }  // namespace android
    247