Add webrtc streamer

Bug: 141887532
Test: locally
Change-Id: I2a0d927470ba1f68cc94b94987a0e0de8b74333e
diff --git a/host/frontend/gcastv2/libandroid/JSONObject.cpp b/host/frontend/gcastv2/libandroid/JSONObject.cpp
new file mode 100644
index 0000000..db658ed
--- /dev/null
+++ b/host/frontend/gcastv2/libandroid/JSONObject.cpp
@@ -0,0 +1,691 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "JSONObject"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/JSONObject.h>
+
+#include <ctype.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+// static
+ssize_t JSONValue::Parse(const char *data, size_t size, JSONValue *out) {
+    size_t offset = 0;
+    while (offset < size && isspace(data[offset])) {
+        ++offset;
+    }
+
+    if (offset == size) {
+        return ERROR_MALFORMED;
+    }
+
+    if (data[offset] == '[') {
+        sp<JSONArray> array = new JSONArray;
+        ++offset;
+
+        for (;;) {
+            while (offset < size && isspace(data[offset])) {
+                ++offset;
+            }
+
+            if (offset == size) {
+                return ERROR_MALFORMED;
+            }
+
+            if (data[offset] == ']') {
+                ++offset;
+                break;
+            }
+
+            JSONValue val;
+            ssize_t n = Parse(&data[offset], size - offset, &val);
+
+            if (n < 0) {
+                return n;
+            }
+
+            array->addValue(val);
+
+            offset += n;
+
+            while (offset < size && isspace(data[offset])) {
+                ++offset;
+            }
+
+            if (offset == size) {
+                return ERROR_MALFORMED;
+            }
+
+            if (data[offset] == ',') {
+                ++offset;
+            } else if (data[offset] != ']') {
+                return ERROR_MALFORMED;
+            }
+        };
+
+        out->setArray(array);
+
+        return offset;
+    } else if (data[offset] == '{') {
+        sp<JSONObject> obj = new JSONObject;
+        ++offset;
+
+        for (;;) {
+            while (offset < size && isspace(data[offset])) {
+                ++offset;
+            }
+
+            if (offset == size) {
+                return ERROR_MALFORMED;
+            }
+
+            if (data[offset] == '}') {
+                ++offset;
+                break;
+            }
+
+            JSONValue key;
+            ssize_t n = Parse(&data[offset], size - offset, &key);
+
+            if (n < 0) {
+                return n;
+            }
+
+            if (key.type() != TYPE_STRING) {
+                return ERROR_MALFORMED;
+            }
+
+            offset += n;
+
+            while (offset < size && isspace(data[offset])) {
+                ++offset;
+            }
+
+            if (offset == size || data[offset] != ':') {
+                return ERROR_MALFORMED;
+            }
+
+            ++offset;
+
+            JSONValue val;
+            n = Parse(&data[offset], size - offset, &val);
+
+            if (n < 0) {
+                return n;
+            }
+
+            std::string keyVal;
+            CHECK(key.getString(&keyVal));
+
+            obj->setValue(keyVal.c_str(), val);
+
+            offset += n;
+
+            while (offset < size && isspace(data[offset])) {
+                ++offset;
+            }
+
+            if (offset == size) {
+                return ERROR_MALFORMED;
+            }
+
+            if (data[offset] == ',') {
+                ++offset;
+            } else if (data[offset] != '}') {
+                return ERROR_MALFORMED;
+            }
+        };
+
+        out->setObject(obj);
+
+        return offset;
+    } else if (data[offset] == '"') {
+        ++offset;
+
+        std::string s;
+        bool escaped = false;
+        while (offset < size) {
+            if (escaped) {
+                char c;
+                switch (data[offset]) {
+                    case '\"':
+                    case '\\':
+                    case '/':
+                        c = data[offset];
+                        break;
+                    case 'b':
+                        c = '\x08';
+                        break;
+                    case 'f':
+                        c = '\x0c';
+                        break;
+                    case 'n':
+                        c = '\x0a';
+                        break;
+                    case 'r':
+                        c = '\x0d';
+                        break;
+                    case 't':
+                        c = '\x09';
+                        break;
+                    default:
+                        return ERROR_MALFORMED;
+                }
+
+                s.append(1, c);
+                ++offset;
+
+                escaped = false;
+                continue;
+            } else if (data[offset] == '\\') {
+                escaped = true;
+                ++offset;
+                continue;
+            } else if (data[offset] == '"') {
+                break;
+            }
+
+            s.append(1, data[offset++]);
+        }
+
+        if (offset == size) {
+            return ERROR_MALFORMED;
+        }
+
+        ++offset;
+        out->setString(s);
+
+        return offset;
+    } else if (isdigit(data[offset]) || data[offset] == '-') {
+        bool negate = false;
+        if (data[offset] == '-') {
+            negate = true;
+            ++offset;
+
+            if (offset == size) {
+                return ERROR_MALFORMED;
+            }
+        }
+
+        size_t firstDigitOffset = offset;
+        while (offset < size && isdigit(data[offset])) {
+            ++offset;
+        }
+
+        size_t numDigits = offset - firstDigitOffset;
+        if (numDigits > 1 && data[firstDigitOffset] == '0') {
+            // No leading zeros.
+            return ERROR_MALFORMED;
+        }
+
+        size_t firstFracDigitOffset = 0;
+        size_t numFracDigits = 0;
+
+        if (offset < size && data[offset] == '.') {
+            ++offset;
+
+            firstFracDigitOffset = offset;
+            while (offset < size && isdigit(data[offset])) {
+                ++offset;
+            }
+
+            numFracDigits = offset - firstFracDigitOffset;
+            if (numFracDigits == 0) {
+                return ERROR_MALFORMED;
+            }
+        }
+
+        bool negateExponent = false;
+        size_t firstExpDigitOffset = 0;
+        size_t numExpDigits = 0;
+
+        if (offset < size && (data[offset] == 'e' || data[offset] == 'E')) {
+            ++offset;
+
+            if (offset == size) {
+                return ERROR_MALFORMED;
+            }
+
+            if (data[offset] == '+' || data[offset] == '-') {
+                if (data[offset] == '-') {
+                    negateExponent = true;
+                }
+
+                ++offset;
+            }
+
+            firstExpDigitOffset = offset;
+            while (offset < size && isdigit(data[offset])) {
+                ++offset;
+            }
+
+            numExpDigits = offset - firstExpDigitOffset;
+            if (numExpDigits == 0) {
+                return ERROR_MALFORMED;
+            }
+        }
+
+        CHECK_EQ(numFracDigits, 0u);
+        CHECK_EQ(numExpDigits, 0u);
+
+        int32_t x = 0;
+        for (size_t i = 0; i < numDigits; ++i) {
+            x *= 10;
+            x += data[firstDigitOffset + i] - '0';
+
+            CHECK_GE(x, 0);
+        }
+
+        if (negate) {
+            x = -x;
+        }
+
+        out->setInt32(x);
+
+        return offset;
+    } else if (offset + 4 <= size && !strncmp("null", &data[offset], 4)) {
+        out->unset();
+        return offset + 4;
+    } else if (offset + 4 <= size && !strncmp("true", &data[offset], 4)) {
+        out->setBoolean(true);
+        return offset + 4;
+    } else if (offset + 5 <= size && !strncmp("false", &data[offset], 5)) {
+        out->setBoolean(false);
+        return offset + 5;
+    }
+
+    return ERROR_MALFORMED;
+}
+
+JSONValue::JSONValue()
+    : mType(TYPE_NULL) {
+}
+
+JSONValue::JSONValue(const JSONValue &other)
+    : mType(TYPE_NULL) {
+    *this = other;
+}
+
+JSONValue &JSONValue::operator=(const JSONValue &other) {
+    if (&other != this) {
+        unset();
+        mType = other.mType;
+        mValue = other.mValue;
+
+        switch (mType) {
+            case TYPE_STRING:
+                mValue.mString = new std::string(*other.mValue.mString);
+                break;
+            case TYPE_OBJECT:
+            case TYPE_ARRAY:
+                mValue.mObjectOrArray->incStrong(this);
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    return *this;
+}
+
+JSONValue::~JSONValue() {
+    unset();
+}
+
+JSONValue::FieldType JSONValue::type() const {
+    return mType;
+}
+
+bool JSONValue::getInt32(int32_t *value) const {
+    if (mType != TYPE_NUMBER) {
+        return false;
+    }
+
+    *value = mValue.mInt32;
+    return true;
+}
+
+bool JSONValue::getString(std::string *value) const {
+    if (mType != TYPE_STRING) {
+        return false;
+    }
+
+    *value = *mValue.mString;
+    return true;
+}
+
+bool JSONValue::getBoolean(bool *value) const {
+    if (mType != TYPE_BOOLEAN) {
+        return false;
+    }
+
+    *value = mValue.mBoolean;
+    return true;
+}
+
+bool JSONValue::getObject(sp<JSONObject> *value) const {
+    if (mType != TYPE_OBJECT) {
+        return false;
+    }
+
+    *value = static_cast<JSONObject *>(mValue.mObjectOrArray);
+    return true;
+}
+
+bool JSONValue::getArray(sp<JSONArray> *value) const {
+    if (mType != TYPE_ARRAY) {
+        return false;
+    }
+
+    *value = static_cast<JSONArray *>(mValue.mObjectOrArray);
+    return true;
+}
+
+void JSONValue::setInt32(int32_t value) {
+    unset();
+
+    mValue.mInt32 = value;
+    mType = TYPE_NUMBER;
+}
+
+void JSONValue::setString(std::string_view value) {
+    unset();
+
+    mValue.mString = new std::string(value);
+    mType = TYPE_STRING;
+}
+
+void JSONValue::setBoolean(bool value) {
+    unset();
+
+    mValue.mBoolean = value;
+    mType = TYPE_BOOLEAN;
+}
+
+void JSONValue::setObject(const sp<JSONObject> &obj) {
+    unset();
+
+    mValue.mObjectOrArray = obj.get();
+    mValue.mObjectOrArray->incStrong(this);
+
+    mType = TYPE_OBJECT;
+}
+
+void JSONValue::setArray(const sp<JSONArray> &array) {
+    unset();
+
+    mValue.mObjectOrArray = array.get();
+    mValue.mObjectOrArray->incStrong(this);
+
+    mType = TYPE_ARRAY;
+}
+
+void JSONValue::unset() {
+    switch (mType) {
+        case TYPE_STRING:
+            delete mValue.mString;
+            break;
+        case TYPE_OBJECT:
+        case TYPE_ARRAY:
+            mValue.mObjectOrArray->decStrong(this);
+            break;
+
+        default:
+            break;
+    }
+
+    mType = TYPE_NULL;
+}
+
+static void EscapeString(const char *in, size_t inSize, std::string *out) {
+    CHECK(in != out->c_str());
+    out->clear();
+
+    for (size_t i = 0; i < inSize; ++i) {
+        char c = in[i];
+        switch (c) {
+            case '\"':
+                out->append("\\\"");
+                break;
+            case '\\':
+                out->append("\\\\");
+                break;
+            case '/':
+                out->append("\\/");
+                break;
+            case '\x08':
+                out->append("\\b");
+                break;
+            case '\x0c':
+                out->append("\\f");
+                break;
+            case '\x0a':
+                out->append("\\n");
+                break;
+            case '\x0d':
+                out->append("\\r");
+                break;
+            case '\x09':
+                out->append("\\t");
+                break;
+            default:
+                out->append(1, c);
+                break;
+        }
+    }
+}
+
+std::string JSONValue::toString(size_t depth, bool indentFirstLine) const {
+    static const char kIndent[] = "                                        ";
+
+    std::string out;
+
+    switch (mType) {
+        case TYPE_STRING:
+        {
+            std::string escaped;
+            EscapeString(
+                    mValue.mString->c_str(), mValue.mString->size(), &escaped);
+
+            out.append("\"");
+            out.append(escaped);
+            out.append("\"");
+            break;
+        }
+
+        case TYPE_NUMBER:
+        {
+            out = StringPrintf("%d", mValue.mInt32);
+            break;
+        }
+
+        case TYPE_BOOLEAN:
+        {
+            out = mValue.mBoolean ? "true" : "false";
+            break;
+        }
+
+        case TYPE_NULL:
+        {
+            out = "null";
+            break;
+        }
+
+        case TYPE_OBJECT:
+        case TYPE_ARRAY:
+        {
+            out = (mType == TYPE_OBJECT) ? "{\n" : "[\n";
+            out.append(mValue.mObjectOrArray->internalToString(depth + 1, true));
+            out.append("\n");
+            out.append(kIndent, 2 * depth);
+            out.append(mType == TYPE_OBJECT ? "}" : "]");
+            break;
+        }
+
+        default:
+            TRESPASS();
+    }
+
+    if (indentFirstLine) {
+        out.insert(0, kIndent, 2 * depth);
+    }
+
+    return out;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// static
+sp<JSONCompound> JSONCompound::Parse(const char *data, size_t size) {
+    JSONValue value;
+    ssize_t result = JSONValue::Parse(data, size, &value);
+
+    if (result < 0) {
+        return NULL;
+    }
+
+    sp<JSONObject> obj;
+    if (value.getObject(&obj)) {
+        return obj;
+    }
+
+    sp<JSONArray> array;
+    if (value.getArray(&array)) {
+        return array;
+    }
+
+    return NULL;
+}
+
+std::string JSONCompound::toString(size_t depth, bool indentFirstLine) const {
+    JSONValue val;
+    if (isObject()) {
+        val.setObject((JSONObject *)this);
+    } else {
+        val.setArray((JSONArray *)this);
+    }
+
+    return val.toString(depth, indentFirstLine);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+JSONObject::JSONObject() {}
+JSONObject::~JSONObject() {}
+
+bool JSONObject::isObject() const {
+    return true;
+}
+
+bool JSONObject::getValue(const char *key, JSONValue *value) const {
+    auto it = mValues.find(key);
+
+    if (it == mValues.end()) {
+        return false;
+    }
+
+    *value = it->second;
+
+    return true;
+}
+
+void JSONObject::setValue(const char *key, const JSONValue &value) {
+    mValues[std::string(key)] = value;
+}
+
+void JSONObject::remove(const char *key) {
+    mValues.erase(key);
+}
+
+std::string JSONObject::internalToString(
+        size_t depth, bool /* indentFirstLine */) const {
+    static const char kIndent[] = "                                        ";
+
+    std::string out;
+    for (auto it = mValues.begin(); it != mValues.end();) {
+        const std::string &key = it->first;
+        std::string escapedKey;
+        EscapeString(key.c_str(), key.size(), &escapedKey);
+
+        out.append(kIndent, 2 * depth);
+        out.append("\"");
+        out.append(escapedKey);
+        out.append("\": ");
+
+        out.append(it->second.toString(depth + 1, false));
+
+        ++it;
+        if (it != mValues.end()) {
+            out.append(",\n");
+        }
+    }
+
+    return out;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+JSONArray::JSONArray() {}
+
+JSONArray::~JSONArray() {}
+
+bool JSONArray::isObject() const {
+    return false;
+}
+
+size_t JSONArray::size() const {
+    return mValues.size();
+}
+
+bool JSONArray::getValue(size_t key, JSONValue *value) const {
+    if (key >= mValues.size()) {
+        return false;
+    }
+
+    *value = mValues[key];
+
+    return true;
+}
+
+void JSONArray::addValue(const JSONValue &value) {
+    mValues.push_back(value);
+}
+
+std::string JSONArray::internalToString(
+        size_t depth, bool /* indentFirstLine */) const {
+    std::string out;
+    for (size_t i = 0; i < mValues.size(); ++i) {
+        out.append(mValues[i].toString(depth));
+
+        if (i + 1 < mValues.size()) {
+            out.append(",\n");
+        }
+    }
+
+    return out;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+}  // namespace android
+