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 status_t DataSource::getSize(off64_t *size) {
     96     *size = 0;
     97 
     98     return ERROR_UNSUPPORTED;
     99 }
    100 
    101 sp<IDataSource> DataSource::getIDataSource() const {
    102     return nullptr;
    103 }
    104 
    105 ////////////////////////////////////////////////////////////////////////////////
    106 
    107 // static
    108 sp<DataSource> DataSource::CreateFromURI(
    109         const sp<IMediaHTTPService> &httpService,
    110         const char *uri,
    111         const KeyedVector<String8, String8> *headers,
    112         String8 *contentType,
    113         HTTPBase *httpSource) {
    114     if (contentType != NULL) {
    115         *contentType = "";
    116     }
    117 
    118     sp<DataSource> source;
    119     if (!strncasecmp("file://", uri, 7)) {
    120         source = new FileSource(uri + 7);
    121     } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
    122         if (httpService == NULL) {
    123             ALOGE("Invalid http service!");
    124             return NULL;
    125         }
    126 
    127         if (httpSource == NULL) {
    128             sp<IMediaHTTPConnection> conn = httpService->makeHTTPConnection();
    129             if (conn == NULL) {
    130                 ALOGE("Failed to make http connection from http service!");
    131                 return NULL;
    132             }
    133             httpSource = new MediaHTTP(conn);
    134         }
    135 
    136         String8 cacheConfig;
    137         bool disconnectAtHighwatermark = false;
    138         KeyedVector<String8, String8> nonCacheSpecificHeaders;
    139         if (headers != NULL) {
    140             nonCacheSpecificHeaders = *headers;
    141             NuCachedSource2::RemoveCacheSpecificHeaders(
    142                     &nonCacheSpecificHeaders,
    143                     &cacheConfig,
    144                     &disconnectAtHighwatermark);
    145         }
    146 
    147         if (httpSource->connect(uri, &nonCacheSpecificHeaders) != OK) {
    148             ALOGE("Failed to connect http source!");
    149             return NULL;
    150         }
    151 
    152         if (contentType != NULL) {
    153             *contentType = httpSource->getMIMEType();
    154         }
    155 
    156         source = NuCachedSource2::Create(
    157                 httpSource,
    158                 cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
    159                 disconnectAtHighwatermark);
    160     } else if (!strncasecmp("data:", uri, 5)) {
    161         source = DataURISource::Create(uri);
    162     } else {
    163         // Assume it's a filename.
    164         source = new FileSource(uri);
    165     }
    166 
    167     if (source == NULL || source->initCheck() != OK) {
    168         return NULL;
    169     }
    170 
    171     return source;
    172 }
    173 
    174 sp<DataSource> DataSource::CreateFromFd(int fd, int64_t offset, int64_t length) {
    175     sp<FileSource> source = new FileSource(fd, offset, length);
    176     return source->initCheck() != OK ? nullptr : source;
    177 }
    178 
    179 sp<DataSource> DataSource::CreateMediaHTTP(const sp<IMediaHTTPService> &httpService) {
    180     if (httpService == NULL) {
    181         return NULL;
    182     }
    183 
    184     sp<IMediaHTTPConnection> conn = httpService->makeHTTPConnection();
    185     if (conn == NULL) {
    186         return NULL;
    187     } else {
    188         return new MediaHTTP(conn);
    189     }
    190 }
    191 
    192 sp<DataSource> DataSource::CreateFromIDataSource(const sp<IDataSource> &source) {
    193     return new TinyCacheSource(new CallbackDataSource(source));
    194 }
    195 
    196 String8 DataSource::getMIMEType() const {
    197     return String8("application/octet-stream");
    198 }
    199 
    200 sp<IDataSource> DataSource::asIDataSource() {
    201     return RemoteDataSource::wrap(sp<DataSource>(this));
    202 }
    203 
    204 }  // namespace android
    205