14bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber/*
24bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber * Copyright (C) 2014 The Android Open Source Project
34bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber *
44bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
54bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber * you may not use this file except in compliance with the License.
64bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber * You may obtain a copy of the License at
74bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber *
84bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
94bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber *
104bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber * Unless required by applicable law or agreed to in writing, software
114bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
124bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber * See the License for the specific language governing permissions and
144bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber * limitations under the License.
154bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber */
164bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
174bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#include <media/stagefright/DataURISource.h>
184bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
194bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#include <media/stagefright/foundation/ABuffer.h>
204bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#include <media/stagefright/foundation/AString.h>
214bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#include <media/stagefright/foundation/base64.h>
224bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
234bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Hubernamespace android {
244bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
254bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber// static
264bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Hubersp<DataURISource> DataURISource::Create(const char *uri) {
274bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    if (strncasecmp("data:", uri, 5)) {
284bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        return NULL;
294bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    }
304bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
314bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    char *commaPos = strrchr(uri, ',');
324bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
334bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    if (commaPos == NULL) {
344bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        return NULL;
354bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    }
364bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
374bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    sp<ABuffer> buffer;
384bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
394bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    AString tmp(&uri[5], commaPos - &uri[5]);
404bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
414bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    if (tmp.endsWith(";base64")) {
424bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        AString encoded(commaPos + 1);
434bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
444bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        // Strip CR and LF...
4569c1e038717d3462ea5991425ba009f0aed148d2Chad Brubaker        for (size_t i = encoded.size(); i > 0;) {
4669c1e038717d3462ea5991425ba009f0aed148d2Chad Brubaker            i--;
474bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber            if (encoded.c_str()[i] == '\r' || encoded.c_str()[i] == '\n') {
484bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber                encoded.erase(i, 1);
494bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber            }
504bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        }
514bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
524bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        buffer = decodeBase64(encoded);
534bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
544bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        if (buffer == NULL) {
554bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber            ALOGE("Malformed base64 encoded content found.");
564bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber            return NULL;
574bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        }
584bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    } else {
594bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#if 0
604bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        size_t dataLen = strlen(uri) - tmp.size() - 6;
614bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        buffer = new ABuffer(dataLen);
624bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        memcpy(buffer->data(), commaPos + 1, dataLen);
634bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
644bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        // unescape
654bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#else
664bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        // MediaPlayer doesn't care for this right now as we don't
674bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        // play any text-based media.
684bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        return NULL;
694bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#endif
704bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    }
714bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
724bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    // We don't really care about charset or mime type.
734bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
744bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    return new DataURISource(buffer);
754bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
764bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
774bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas HuberDataURISource::DataURISource(const sp<ABuffer> &buffer)
784bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    : mBuffer(buffer) {
794bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
804bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
814bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas HuberDataURISource::~DataURISource() {
824bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
834bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
844bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huberstatus_t DataURISource::initCheck() const {
854bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    return OK;
864bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
874bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
884bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huberssize_t DataURISource::readAt(off64_t offset, void *data, size_t size) {
89a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    if ((offset < 0) || (offset >= (off64_t)mBuffer->size())) {
904bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        return 0;
914bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    }
924bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
934bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    size_t copy = mBuffer->size() - offset;
944bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    if (copy > size) {
954bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        copy = size;
964bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    }
974bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
984bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    memcpy(data, mBuffer->data() + offset, copy);
994bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
1004bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    return copy;
1014bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
1024bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
1034bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huberstatus_t DataURISource::getSize(off64_t *size) {
1044bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    *size = mBuffer->size();
1054bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
1064bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    return OK;
1074bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
1084bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
1094bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}  // namespace android
1104bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
111