1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker #include <datasource/DataURISource.h>
17*ec779b8eSAndroid Build Coastguard Worker
18*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABuffer.h>
19*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AString.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/base64.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker namespace android {
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker // static
Create(const char * uri)25*ec779b8eSAndroid Build Coastguard Worker sp<DataURISource> DataURISource::Create(const char *uri) {
26*ec779b8eSAndroid Build Coastguard Worker if (strncasecmp("data:", uri, 5)) {
27*ec779b8eSAndroid Build Coastguard Worker return NULL;
28*ec779b8eSAndroid Build Coastguard Worker }
29*ec779b8eSAndroid Build Coastguard Worker
30*ec779b8eSAndroid Build Coastguard Worker const char *commaPos = strrchr(uri, ',');
31*ec779b8eSAndroid Build Coastguard Worker
32*ec779b8eSAndroid Build Coastguard Worker if (commaPos == NULL) {
33*ec779b8eSAndroid Build Coastguard Worker return NULL;
34*ec779b8eSAndroid Build Coastguard Worker }
35*ec779b8eSAndroid Build Coastguard Worker
36*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> buffer;
37*ec779b8eSAndroid Build Coastguard Worker
38*ec779b8eSAndroid Build Coastguard Worker AString tmp(&uri[5], commaPos - &uri[5]);
39*ec779b8eSAndroid Build Coastguard Worker
40*ec779b8eSAndroid Build Coastguard Worker if (tmp.endsWith(";base64")) {
41*ec779b8eSAndroid Build Coastguard Worker
42*ec779b8eSAndroid Build Coastguard Worker // strip all CR and LF characters.
43*ec779b8eSAndroid Build Coastguard Worker const char *src = commaPos+1;
44*ec779b8eSAndroid Build Coastguard Worker int len = strlen(src) + 1;
45*ec779b8eSAndroid Build Coastguard Worker char *cleansed = (char *) malloc(len);
46*ec779b8eSAndroid Build Coastguard Worker if (cleansed == NULL) return NULL;
47*ec779b8eSAndroid Build Coastguard Worker char *keeping = cleansed;
48*ec779b8eSAndroid Build Coastguard Worker int left = len;
49*ec779b8eSAndroid Build Coastguard Worker for (int i = 0; i < len ; i++)
50*ec779b8eSAndroid Build Coastguard Worker {
51*ec779b8eSAndroid Build Coastguard Worker const char c = *src++;
52*ec779b8eSAndroid Build Coastguard Worker if (c == '\r' || c == '\n') {
53*ec779b8eSAndroid Build Coastguard Worker continue;
54*ec779b8eSAndroid Build Coastguard Worker }
55*ec779b8eSAndroid Build Coastguard Worker *keeping++ = c;
56*ec779b8eSAndroid Build Coastguard Worker left--;
57*ec779b8eSAndroid Build Coastguard Worker }
58*ec779b8eSAndroid Build Coastguard Worker memset(keeping, 0, left);
59*ec779b8eSAndroid Build Coastguard Worker
60*ec779b8eSAndroid Build Coastguard Worker AString encoded(cleansed);
61*ec779b8eSAndroid Build Coastguard Worker free(cleansed);
62*ec779b8eSAndroid Build Coastguard Worker
63*ec779b8eSAndroid Build Coastguard Worker buffer = decodeBase64(encoded);
64*ec779b8eSAndroid Build Coastguard Worker
65*ec779b8eSAndroid Build Coastguard Worker if (buffer == NULL) {
66*ec779b8eSAndroid Build Coastguard Worker ALOGE("Malformed base64 encoded content found.");
67*ec779b8eSAndroid Build Coastguard Worker return NULL;
68*ec779b8eSAndroid Build Coastguard Worker }
69*ec779b8eSAndroid Build Coastguard Worker } else {
70*ec779b8eSAndroid Build Coastguard Worker #if 0
71*ec779b8eSAndroid Build Coastguard Worker size_t dataLen = strlen(uri) - tmp.size() - 6;
72*ec779b8eSAndroid Build Coastguard Worker buffer = new ABuffer(dataLen);
73*ec779b8eSAndroid Build Coastguard Worker memcpy(buffer->data(), commaPos + 1, dataLen);
74*ec779b8eSAndroid Build Coastguard Worker
75*ec779b8eSAndroid Build Coastguard Worker // unescape
76*ec779b8eSAndroid Build Coastguard Worker #else
77*ec779b8eSAndroid Build Coastguard Worker // MediaPlayer doesn't care for this right now as we don't
78*ec779b8eSAndroid Build Coastguard Worker // play any text-based media.
79*ec779b8eSAndroid Build Coastguard Worker return NULL;
80*ec779b8eSAndroid Build Coastguard Worker #endif
81*ec779b8eSAndroid Build Coastguard Worker }
82*ec779b8eSAndroid Build Coastguard Worker
83*ec779b8eSAndroid Build Coastguard Worker // We don't really care about charset or mime type.
84*ec779b8eSAndroid Build Coastguard Worker
85*ec779b8eSAndroid Build Coastguard Worker return new DataURISource(buffer);
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker
DataURISource(const sp<ABuffer> & buffer)88*ec779b8eSAndroid Build Coastguard Worker DataURISource::DataURISource(const sp<ABuffer> &buffer)
89*ec779b8eSAndroid Build Coastguard Worker : mBuffer(buffer) {
90*ec779b8eSAndroid Build Coastguard Worker }
91*ec779b8eSAndroid Build Coastguard Worker
~DataURISource()92*ec779b8eSAndroid Build Coastguard Worker DataURISource::~DataURISource() {
93*ec779b8eSAndroid Build Coastguard Worker }
94*ec779b8eSAndroid Build Coastguard Worker
initCheck() const95*ec779b8eSAndroid Build Coastguard Worker status_t DataURISource::initCheck() const {
96*ec779b8eSAndroid Build Coastguard Worker return OK;
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker
readAt(off64_t offset,void * data,size_t size)99*ec779b8eSAndroid Build Coastguard Worker ssize_t DataURISource::readAt(off64_t offset, void *data, size_t size) {
100*ec779b8eSAndroid Build Coastguard Worker if ((offset < 0) || (offset >= (off64_t)mBuffer->size())) {
101*ec779b8eSAndroid Build Coastguard Worker return 0;
102*ec779b8eSAndroid Build Coastguard Worker }
103*ec779b8eSAndroid Build Coastguard Worker
104*ec779b8eSAndroid Build Coastguard Worker size_t copy = mBuffer->size() - offset;
105*ec779b8eSAndroid Build Coastguard Worker if (copy > size) {
106*ec779b8eSAndroid Build Coastguard Worker copy = size;
107*ec779b8eSAndroid Build Coastguard Worker }
108*ec779b8eSAndroid Build Coastguard Worker
109*ec779b8eSAndroid Build Coastguard Worker memcpy(data, mBuffer->data() + offset, copy);
110*ec779b8eSAndroid Build Coastguard Worker
111*ec779b8eSAndroid Build Coastguard Worker return copy;
112*ec779b8eSAndroid Build Coastguard Worker }
113*ec779b8eSAndroid Build Coastguard Worker
getSize(off64_t * size)114*ec779b8eSAndroid Build Coastguard Worker status_t DataURISource::getSize(off64_t *size) {
115*ec779b8eSAndroid Build Coastguard Worker *size = mBuffer->size();
116*ec779b8eSAndroid Build Coastguard Worker
117*ec779b8eSAndroid Build Coastguard Worker return OK;
118*ec779b8eSAndroid Build Coastguard Worker }
119*ec779b8eSAndroid Build Coastguard Worker
120*ec779b8eSAndroid Build Coastguard Worker } // namespace android
121*ec779b8eSAndroid Build Coastguard Worker
122