• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/AMRExtractor.h"
20 
21 #include "include/AACExtractor.h"
22 #include "include/DRMExtractor.h"
23 #include "include/FLACExtractor.h"
24 #include "include/HTTPBase.h"
25 #include "include/MP3Extractor.h"
26 #include "include/MPEG2PSExtractor.h"
27 #include "include/MPEG2TSExtractor.h"
28 #include "include/MPEG4Extractor.h"
29 #include "include/NuCachedSource2.h"
30 #include "include/OggExtractor.h"
31 #include "include/WAVExtractor.h"
32 #include "include/WVMExtractor.h"
33 
34 #include "matroska/MatroskaExtractor.h"
35 
36 #include <media/IMediaHTTPConnection.h>
37 #include <media/IMediaHTTPService.h>
38 #include <media/stagefright/foundation/ADebug.h>
39 #include <media/stagefright/foundation/AMessage.h>
40 #include <media/stagefright/DataSource.h>
41 #include <media/stagefright/DataURISource.h>
42 #include <media/stagefright/FileSource.h>
43 #include <media/stagefright/MediaErrors.h>
44 #include <media/stagefright/MediaHTTP.h>
45 #include <utils/String8.h>
46 
47 #include <cutils/properties.h>
48 
49 namespace android {
50 
getUInt16(off64_t offset,uint16_t * x)51 bool DataSource::getUInt16(off64_t offset, uint16_t *x) {
52     *x = 0;
53 
54     uint8_t byte[2];
55     if (readAt(offset, byte, 2) != 2) {
56         return false;
57     }
58 
59     *x = (byte[0] << 8) | byte[1];
60 
61     return true;
62 }
63 
getUInt24(off64_t offset,uint32_t * x)64 bool DataSource::getUInt24(off64_t offset, uint32_t *x) {
65     *x = 0;
66 
67     uint8_t byte[3];
68     if (readAt(offset, byte, 3) != 3) {
69         return false;
70     }
71 
72     *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];
73 
74     return true;
75 }
76 
getUInt32(off64_t offset,uint32_t * x)77 bool DataSource::getUInt32(off64_t offset, uint32_t *x) {
78     *x = 0;
79 
80     uint32_t tmp;
81     if (readAt(offset, &tmp, 4) != 4) {
82         return false;
83     }
84 
85     *x = ntohl(tmp);
86 
87     return true;
88 }
89 
getUInt64(off64_t offset,uint64_t * x)90 bool DataSource::getUInt64(off64_t offset, uint64_t *x) {
91     *x = 0;
92 
93     uint64_t tmp;
94     if (readAt(offset, &tmp, 8) != 8) {
95         return false;
96     }
97 
98     *x = ntoh64(tmp);
99 
100     return true;
101 }
102 
getSize(off64_t * size)103 status_t DataSource::getSize(off64_t *size) {
104     *size = 0;
105 
106     return ERROR_UNSUPPORTED;
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 
111 Mutex DataSource::gSnifferMutex;
112 List<DataSource::SnifferFunc> DataSource::gSniffers;
113 bool DataSource::gSniffersRegistered = false;
114 
sniff(String8 * mimeType,float * confidence,sp<AMessage> * meta)115 bool DataSource::sniff(
116         String8 *mimeType, float *confidence, sp<AMessage> *meta) {
117     *mimeType = "";
118     *confidence = 0.0f;
119     meta->clear();
120 
121     {
122         Mutex::Autolock autoLock(gSnifferMutex);
123         if (!gSniffersRegistered) {
124             return false;
125         }
126     }
127 
128     for (List<SnifferFunc>::iterator it = gSniffers.begin();
129          it != gSniffers.end(); ++it) {
130         String8 newMimeType;
131         float newConfidence;
132         sp<AMessage> newMeta;
133         if ((*it)(this, &newMimeType, &newConfidence, &newMeta)) {
134             if (newConfidence > *confidence) {
135                 *mimeType = newMimeType;
136                 *confidence = newConfidence;
137                 *meta = newMeta;
138             }
139         }
140     }
141 
142     return *confidence > 0.0;
143 }
144 
145 // static
RegisterSniffer_l(SnifferFunc func)146 void DataSource::RegisterSniffer_l(SnifferFunc func) {
147     for (List<SnifferFunc>::iterator it = gSniffers.begin();
148          it != gSniffers.end(); ++it) {
149         if (*it == func) {
150             return;
151         }
152     }
153 
154     gSniffers.push_back(func);
155 }
156 
157 // static
RegisterDefaultSniffers()158 void DataSource::RegisterDefaultSniffers() {
159     Mutex::Autolock autoLock(gSnifferMutex);
160     if (gSniffersRegistered) {
161         return;
162     }
163 
164     RegisterSniffer_l(SniffMPEG4);
165     RegisterSniffer_l(SniffMatroska);
166     RegisterSniffer_l(SniffOgg);
167     RegisterSniffer_l(SniffWAV);
168     RegisterSniffer_l(SniffFLAC);
169     RegisterSniffer_l(SniffAMR);
170     RegisterSniffer_l(SniffMPEG2TS);
171     RegisterSniffer_l(SniffMP3);
172     RegisterSniffer_l(SniffAAC);
173     RegisterSniffer_l(SniffMPEG2PS);
174     RegisterSniffer_l(SniffWVM);
175 
176     char value[PROPERTY_VALUE_MAX];
177     if (property_get("drm.service.enabled", value, NULL)
178             && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
179         RegisterSniffer_l(SniffDRM);
180     }
181     gSniffersRegistered = true;
182 }
183 
184 // static
CreateFromURI(const sp<IMediaHTTPService> & httpService,const char * uri,const KeyedVector<String8,String8> * headers,String8 * contentType,HTTPBase * httpSource)185 sp<DataSource> DataSource::CreateFromURI(
186         const sp<IMediaHTTPService> &httpService,
187         const char *uri,
188         const KeyedVector<String8, String8> *headers,
189         String8 *contentType,
190         HTTPBase *httpSource) {
191     if (contentType != NULL) {
192         *contentType = "";
193     }
194 
195     bool isWidevine = !strncasecmp("widevine://", uri, 11);
196 
197     sp<DataSource> source;
198     if (!strncasecmp("file://", uri, 7)) {
199         source = new FileSource(uri + 7);
200     } else if (!strncasecmp("http://", uri, 7)
201             || !strncasecmp("https://", uri, 8)
202             || isWidevine) {
203         if (httpService == NULL) {
204             ALOGE("Invalid http service!");
205             return NULL;
206         }
207 
208         if (httpSource == NULL) {
209             sp<IMediaHTTPConnection> conn = httpService->makeHTTPConnection();
210             if (conn == NULL) {
211                 ALOGE("Failed to make http connection from http service!");
212                 return NULL;
213             }
214             httpSource = new MediaHTTP(conn);
215         }
216 
217         String8 tmp;
218         if (isWidevine) {
219             tmp = String8("http://");
220             tmp.append(uri + 11);
221 
222             uri = tmp.string();
223         }
224 
225         String8 cacheConfig;
226         bool disconnectAtHighwatermark;
227         KeyedVector<String8, String8> nonCacheSpecificHeaders;
228         if (headers != NULL) {
229             nonCacheSpecificHeaders = *headers;
230             NuCachedSource2::RemoveCacheSpecificHeaders(
231                     &nonCacheSpecificHeaders,
232                     &cacheConfig,
233                     &disconnectAtHighwatermark);
234         }
235 
236         if (httpSource->connect(uri, &nonCacheSpecificHeaders) != OK) {
237             ALOGE("Failed to connect http source!");
238             return NULL;
239         }
240 
241         if (!isWidevine) {
242             if (contentType != NULL) {
243                 *contentType = httpSource->getMIMEType();
244             }
245 
246             source = new NuCachedSource2(
247                     httpSource,
248                     cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
249                     disconnectAtHighwatermark);
250         } else {
251             // We do not want that prefetching, caching, datasource wrapper
252             // in the widevine:// case.
253             source = httpSource;
254         }
255     } else if (!strncasecmp("data:", uri, 5)) {
256         source = DataURISource::Create(uri);
257     } else {
258         // Assume it's a filename.
259         source = new FileSource(uri);
260     }
261 
262     if (source == NULL || source->initCheck() != OK) {
263         return NULL;
264     }
265 
266     return source;
267 }
268 
CreateMediaHTTP(const sp<IMediaHTTPService> & httpService)269 sp<DataSource> DataSource::CreateMediaHTTP(const sp<IMediaHTTPService> &httpService) {
270     if (httpService == NULL) {
271         return NULL;
272     }
273 
274     sp<IMediaHTTPConnection> conn = httpService->makeHTTPConnection();
275     if (conn == NULL) {
276         return NULL;
277     } else {
278         return new MediaHTTP(conn);
279     }
280 }
281 
getMIMEType() const282 String8 DataSource::getMIMEType() const {
283     return String8("application/octet-stream");
284 }
285 
286 }  // namespace android
287