/*
 * Copyright 2017 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 "NuPlayer2Drm"

#include "NuPlayer2Drm.h"

#include <media/NdkWrapper.h>
#include <utils/Log.h>
#include <sstream>

namespace android {

Vector<DrmUUID> NuPlayer2Drm::parsePSSH(const void *pssh, size_t psshsize)
{
    Vector<DrmUUID> drmSchemes, empty;
    const int DATALEN_SIZE = 4;

    // the format of the buffer is 1 or more of:
    //    {
    //        16 byte uuid
    //        4 byte data length N
    //        N bytes of data
    //    }
    // Determine the number of entries in the source data.
    // Since we got the data from stagefright, we trust it is valid and properly formatted.

    const uint8_t *data = (const uint8_t*)pssh;
    size_t len = psshsize;
    size_t numentries = 0;
    while (len > 0) {
        if (len < DrmUUID::UUID_SIZE) {
            ALOGE("ParsePSSH: invalid PSSH data");
            return empty;
        }

        const uint8_t *uuidPtr = data;

        // skip uuid
        data += DrmUUID::UUID_SIZE;
        len -= DrmUUID::UUID_SIZE;

        // get data length
        if (len < DATALEN_SIZE) {
            ALOGE("ParsePSSH: invalid PSSH data");
            return empty;
        }

        uint32_t datalen = *((uint32_t*)data);
        data += DATALEN_SIZE;
        len -= DATALEN_SIZE;

        if (len < datalen) {
            ALOGE("ParsePSSH: invalid PSSH data");
            return empty;
        }

        // skip the data
        data += datalen;
        len -= datalen;

        DrmUUID _uuid(uuidPtr);
        drmSchemes.add(_uuid);

        ALOGV("ParsePSSH[%zu]: %s: %s", numentries,
                _uuid.toHexString().string(),
                DrmUUID::arrayToHex(data, datalen).string()
             );

        numentries++;
    }

    return drmSchemes;
}

Vector<DrmUUID> NuPlayer2Drm::getSupportedDrmSchemes(const void *pssh, size_t psshsize)
{
    Vector<DrmUUID> psshDRMs = parsePSSH(pssh, psshsize);

    Vector<DrmUUID> supportedDRMs;
    for (size_t i = 0; i < psshDRMs.size(); i++) {
        DrmUUID uuid = psshDRMs[i];
        if (AMediaDrmWrapper::isCryptoSchemeSupported(uuid.ptr(), NULL)) {
            supportedDRMs.add(uuid);
        }
    }

    ALOGV("getSupportedDrmSchemes: psshDRMs: %zu supportedDRMs: %zu",
            psshDRMs.size(), supportedDRMs.size());

    return supportedDRMs;
}

sp<ABuffer> NuPlayer2Drm::retrieveDrmInfo(const void *pssh, uint32_t psshsize)
{
    std::ostringstream buf;

    // 1) PSSH bytes
    buf.write(reinterpret_cast<const char *>(&psshsize), sizeof(psshsize));
    buf.write(reinterpret_cast<const char *>(pssh), psshsize);

    ALOGV("retrieveDrmInfo: MEDIA2_DRM_INFO  PSSH: size: %u %s", psshsize,
            DrmUUID::arrayToHex((uint8_t*)pssh, psshsize).string());

    // 2) supportedDRMs
    Vector<DrmUUID> supportedDRMs = getSupportedDrmSchemes(pssh, psshsize);
    uint32_t n = supportedDRMs.size();
    buf.write(reinterpret_cast<char *>(&n), sizeof(n));
    for (size_t i = 0; i < n; i++) {
        DrmUUID uuid = supportedDRMs[i];
        buf.write(reinterpret_cast<const char *>(&n), sizeof(n));
        buf.write(reinterpret_cast<const char *>(uuid.ptr()), DrmUUID::UUID_SIZE);

        ALOGV("retrieveDrmInfo: MEDIA2_DRM_INFO  supportedScheme[%zu] %s", i,
                uuid.toHexString().string());
    }

    sp<ABuffer> drmInfoBuffer = ABuffer::CreateAsCopy(buf.str().c_str(), buf.tellp());
    return drmInfoBuffer;
}

sp<ABuffer> NuPlayer2Drm::retrieveDrmInfo(PsshInfo *psshInfo)
{

    std::ostringstream pssh, drmInfo;

    // 0) Generate PSSH bytes
    for (size_t i = 0; i < psshInfo->numentries; i++) {
        PsshEntry *entry = &psshInfo->entries[i];
        uint32_t datalen = entry->datalen;
        pssh.write(reinterpret_cast<const char *>(&entry->uuid), sizeof(entry->uuid));
        pssh.write(reinterpret_cast<const char *>(&datalen), sizeof(datalen));
        pssh.write(reinterpret_cast<const char *>(entry->data), datalen);
    }

    uint32_t psshSize = pssh.tellp();
    std::string psshBase = pssh.str();
    const auto* psshPtr = reinterpret_cast<const uint8_t*>(psshBase.c_str());
    ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO  PSSH: size: %u %s", psshSize,
            DrmUUID::arrayToHex(psshPtr, psshSize).string());

    // 1) Write PSSH bytes
    drmInfo.write(reinterpret_cast<const char *>(&psshSize), sizeof(psshSize));
    drmInfo.write(reinterpret_cast<const char *>(pssh.str().c_str()), psshSize);

    // 2) Write supportedDRMs
    uint32_t numentries = psshInfo->numentries;
    drmInfo.write(reinterpret_cast<const char *>(&numentries), sizeof(numentries));
    for (size_t i = 0; i < numentries; i++) {
        PsshEntry *entry = &psshInfo->entries[i];
        drmInfo.write(reinterpret_cast<const char *>(&entry->uuid), sizeof(entry->uuid));
        ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO  supportedScheme[%zu] %s", i,
                DrmUUID::arrayToHex((const uint8_t*)&entry->uuid, sizeof(AMediaUUID)).string());
    }

    sp<ABuffer> drmInfoBuf = ABuffer::CreateAsCopy(drmInfo.str().c_str(), drmInfo.tellp());
    drmInfoBuf->setRange(0, drmInfo.tellp());
    return drmInfoBuf;
}

}   // namespace android
