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...
454bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        for (size_t i = encoded.size(); i-- > 0;) {
464bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber            if (encoded.c_str()[i] == '\r' || encoded.c_str()[i] == '\n') {
474bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber                encoded.erase(i, 1);
484bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber            }
494bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        }
504bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
514bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        buffer = decodeBase64(encoded);
524bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
534bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        if (buffer == NULL) {
544bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber            ALOGE("Malformed base64 encoded content found.");
554bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber            return NULL;
564bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        }
574bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    } else {
584bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#if 0
594bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        size_t dataLen = strlen(uri) - tmp.size() - 6;
604bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        buffer = new ABuffer(dataLen);
614bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        memcpy(buffer->data(), commaPos + 1, dataLen);
624bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
634bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        // unescape
644bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#else
654bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        // MediaPlayer doesn't care for this right now as we don't
664bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        // play any text-based media.
674bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        return NULL;
684bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber#endif
694bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    }
704bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
714bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    // We don't really care about charset or mime type.
724bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
734bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    return new DataURISource(buffer);
744bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
754bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
764bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas HuberDataURISource::DataURISource(const sp<ABuffer> &buffer)
774bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    : mBuffer(buffer) {
784bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
794bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
804bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas HuberDataURISource::~DataURISource() {
814bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
824bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
834bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huberstatus_t DataURISource::initCheck() const {
844bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    return OK;
854bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
864bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
874bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huberssize_t DataURISource::readAt(off64_t offset, void *data, size_t size) {
88a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    if ((offset < 0) || (offset >= (off64_t)mBuffer->size())) {
894bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        return 0;
904bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    }
914bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
924bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    size_t copy = mBuffer->size() - offset;
934bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    if (copy > size) {
944bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber        copy = size;
954bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    }
964bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
974bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    memcpy(data, mBuffer->data() + offset, copy);
984bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
994bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    return copy;
1004bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
1014bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
1024bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huberstatus_t DataURISource::getSize(off64_t *size) {
1034bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    *size = mBuffer->size();
1044bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
1054bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber    return OK;
1064bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}
1074bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
1084bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber}  // namespace android
1094bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber
110