/*
 * Copyright 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 "MediaSender"
#include <utils/Log.h>

#include "MediaSender.h"

#include "rtp/RTPSender.h"
#include "source/TSPacketizer.h"

#include "include/avc_utils.h"

#include <media/IHDCP.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/ANetworkSession.h>
#include <ui/GraphicBuffer.h>

namespace android {

MediaSender::MediaSender(
        const sp<ANetworkSession> &netSession,
        const sp<AMessage> &notify)
    : mNetSession(netSession),
      mNotify(notify),
      mMode(MODE_UNDEFINED),
      mGeneration(0),
      mPrevTimeUs(-1ll),
      mInitDoneCount(0),
      mLogFile(NULL) {
    // mLogFile = fopen("/data/misc/log.ts", "wb");
}

MediaSender::~MediaSender() {
    if (mLogFile != NULL) {
        fclose(mLogFile);
        mLogFile = NULL;
    }
}

status_t MediaSender::setHDCP(const sp<IHDCP> &hdcp) {
    if (mMode != MODE_UNDEFINED) {
        return INVALID_OPERATION;
    }

    mHDCP = hdcp;

    return OK;
}

ssize_t MediaSender::addTrack(const sp<AMessage> &format, uint32_t flags) {
    if (mMode != MODE_UNDEFINED) {
        return INVALID_OPERATION;
    }

    TrackInfo info;
    info.mFormat = format;
    info.mFlags = flags;
    info.mPacketizerTrackIndex = -1;

    AString mime;
    CHECK(format->findString("mime", &mime));
    info.mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);

    size_t index = mTrackInfos.size();
    mTrackInfos.push_back(info);

    return index;
}

status_t MediaSender::initAsync(
        ssize_t trackIndex,
        const char *remoteHost,
        int32_t remoteRTPPort,
        RTPSender::TransportMode rtpMode,
        int32_t remoteRTCPPort,
        RTPSender::TransportMode rtcpMode,
        int32_t *localRTPPort) {
    if (trackIndex < 0) {
        if (mMode != MODE_UNDEFINED) {
            return INVALID_OPERATION;
        }

        uint32_t flags = 0;
        if (mHDCP != NULL) {
            // XXX Determine proper HDCP version.
            flags |= TSPacketizer::EMIT_HDCP20_DESCRIPTOR;
        }
        mTSPacketizer = new TSPacketizer(flags);

        status_t err = OK;
        for (size_t i = 0; i < mTrackInfos.size(); ++i) {
            TrackInfo *info = &mTrackInfos.editItemAt(i);

            ssize_t packetizerTrackIndex =
                mTSPacketizer->addTrack(info->mFormat);

            if (packetizerTrackIndex < 0) {
                err = packetizerTrackIndex;
                break;
            }

            info->mPacketizerTrackIndex = packetizerTrackIndex;
        }

        if (err == OK) {
            sp<AMessage> notify = new AMessage(kWhatSenderNotify, this);
            notify->setInt32("generation", mGeneration);
            mTSSender = new RTPSender(mNetSession, notify);
            looper()->registerHandler(mTSSender);

            err = mTSSender->initAsync(
                    remoteHost,
                    remoteRTPPort,
                    rtpMode,
                    remoteRTCPPort,
                    rtcpMode,
                    localRTPPort);

            if (err != OK) {
                looper()->unregisterHandler(mTSSender->id());
                mTSSender.clear();
            }
        }

        if (err != OK) {
            for (size_t i = 0; i < mTrackInfos.size(); ++i) {
                TrackInfo *info = &mTrackInfos.editItemAt(i);
                info->mPacketizerTrackIndex = -1;
            }

            mTSPacketizer.clear();
            return err;
        }

        mMode = MODE_TRANSPORT_STREAM;
        mInitDoneCount = 1;

        return OK;
    }

    if (mMode == MODE_TRANSPORT_STREAM) {
        return INVALID_OPERATION;
    }

    if ((size_t)trackIndex >= mTrackInfos.size()) {
        return -ERANGE;
    }

    TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);

    if (info->mSender != NULL) {
        return INVALID_OPERATION;
    }

    sp<AMessage> notify = new AMessage(kWhatSenderNotify, this);
    notify->setInt32("generation", mGeneration);
    notify->setSize("trackIndex", trackIndex);

    info->mSender = new RTPSender(mNetSession, notify);
    looper()->registerHandler(info->mSender);

    status_t err = info->mSender->initAsync(
            remoteHost,
            remoteRTPPort,
            rtpMode,
            remoteRTCPPort,
            rtcpMode,
            localRTPPort);

    if (err != OK) {
        looper()->unregisterHandler(info->mSender->id());
        info->mSender.clear();

        return err;
    }

    if (mMode == MODE_UNDEFINED) {
        mInitDoneCount = mTrackInfos.size();
    }

    mMode = MODE_ELEMENTARY_STREAMS;

    return OK;
}

status_t MediaSender::queueAccessUnit(
        size_t trackIndex, const sp<ABuffer> &accessUnit) {
    if (mMode == MODE_UNDEFINED) {
        return INVALID_OPERATION;
    }

    if (trackIndex >= mTrackInfos.size()) {
        return -ERANGE;
    }

    if (mMode == MODE_TRANSPORT_STREAM) {
        TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);
        info->mAccessUnits.push_back(accessUnit);

        mTSPacketizer->extractCSDIfNecessary(info->mPacketizerTrackIndex);

        for (;;) {
            ssize_t minTrackIndex = -1;
            int64_t minTimeUs = -1ll;

            for (size_t i = 0; i < mTrackInfos.size(); ++i) {
                const TrackInfo &info = mTrackInfos.itemAt(i);

                if (info.mAccessUnits.empty()) {
                    minTrackIndex = -1;
                    minTimeUs = -1ll;
                    break;
                }

                int64_t timeUs;
                const sp<ABuffer> &accessUnit = *info.mAccessUnits.begin();
                CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));

                if (minTrackIndex < 0 || timeUs < minTimeUs) {
                    minTrackIndex = i;
                    minTimeUs = timeUs;
                }
            }

            if (minTrackIndex < 0) {
                return OK;
            }

            TrackInfo *info = &mTrackInfos.editItemAt(minTrackIndex);
            sp<ABuffer> accessUnit = *info->mAccessUnits.begin();
            info->mAccessUnits.erase(info->mAccessUnits.begin());

            sp<ABuffer> tsPackets;
            status_t err = packetizeAccessUnit(
                    minTrackIndex, accessUnit, &tsPackets);

            if (err == OK) {
                if (mLogFile != NULL) {
                    fwrite(tsPackets->data(), 1, tsPackets->size(), mLogFile);
                }

                int64_t timeUs;
                CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
                tsPackets->meta()->setInt64("timeUs", timeUs);

                err = mTSSender->queueBuffer(
                        tsPackets,
                        33 /* packetType */,
                        RTPSender::PACKETIZATION_TRANSPORT_STREAM);
            }

            if (err != OK) {
                return err;
            }
        }
    }

    TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);

    return info->mSender->queueBuffer(
            accessUnit,
            info->mIsAudio ? 96 : 97 /* packetType */,
            info->mIsAudio
                ? RTPSender::PACKETIZATION_AAC : RTPSender::PACKETIZATION_H264);
}

void MediaSender::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatSenderNotify:
        {
            int32_t generation;
            CHECK(msg->findInt32("generation", &generation));
            if (generation != mGeneration) {
                break;
            }

            onSenderNotify(msg);
            break;
        }

        default:
            TRESPASS();
    }
}

void MediaSender::onSenderNotify(const sp<AMessage> &msg) {
    int32_t what;
    CHECK(msg->findInt32("what", &what));

    switch (what) {
        case RTPSender::kWhatInitDone:
        {
            --mInitDoneCount;

            int32_t err;
            CHECK(msg->findInt32("err", &err));

            if (err != OK) {
                notifyInitDone(err);
                ++mGeneration;
                break;
            }

            if (mInitDoneCount == 0) {
                notifyInitDone(OK);
            }
            break;
        }

        case RTPSender::kWhatError:
        {
            int32_t err;
            CHECK(msg->findInt32("err", &err));

            notifyError(err);
            break;
        }

        case kWhatNetworkStall:
        {
            size_t numBytesQueued;
            CHECK(msg->findSize("numBytesQueued", &numBytesQueued));

            notifyNetworkStall(numBytesQueued);
            break;
        }

        case kWhatInformSender:
        {
            int64_t avgLatencyUs;
            CHECK(msg->findInt64("avgLatencyUs", &avgLatencyUs));

            int64_t maxLatencyUs;
            CHECK(msg->findInt64("maxLatencyUs", &maxLatencyUs));

            sp<AMessage> notify = mNotify->dup();
            notify->setInt32("what", kWhatInformSender);
            notify->setInt64("avgLatencyUs", avgLatencyUs);
            notify->setInt64("maxLatencyUs", maxLatencyUs);
            notify->post();
            break;
        }

        default:
            TRESPASS();
    }
}

void MediaSender::notifyInitDone(status_t err) {
    sp<AMessage> notify = mNotify->dup();
    notify->setInt32("what", kWhatInitDone);
    notify->setInt32("err", err);
    notify->post();
}

void MediaSender::notifyError(status_t err) {
    sp<AMessage> notify = mNotify->dup();
    notify->setInt32("what", kWhatError);
    notify->setInt32("err", err);
    notify->post();
}

void MediaSender::notifyNetworkStall(size_t numBytesQueued) {
    sp<AMessage> notify = mNotify->dup();
    notify->setInt32("what", kWhatNetworkStall);
    notify->setSize("numBytesQueued", numBytesQueued);
    notify->post();
}

status_t MediaSender::packetizeAccessUnit(
        size_t trackIndex,
        sp<ABuffer> accessUnit,
        sp<ABuffer> *tsPackets) {
    const TrackInfo &info = mTrackInfos.itemAt(trackIndex);

    uint32_t flags = 0;

    bool isHDCPEncrypted = false;
    uint64_t inputCTR;
    uint8_t HDCP_private_data[16];

    bool manuallyPrependSPSPPS =
        !info.mIsAudio
        && (info.mFlags & FLAG_MANUALLY_PREPEND_SPS_PPS)
        && IsIDR(accessUnit);

    if (mHDCP != NULL && !info.mIsAudio) {
        isHDCPEncrypted = true;

        if (manuallyPrependSPSPPS) {
            accessUnit = mTSPacketizer->prependCSD(
                    info.mPacketizerTrackIndex, accessUnit);
        }

        status_t err;
        native_handle_t* handle;
        if (accessUnit->meta()->findPointer("handle", (void**)&handle)
                && handle != NULL) {
            int32_t rangeLength, rangeOffset;
            sp<AMessage> notify;
            CHECK(accessUnit->meta()->findInt32("rangeOffset", &rangeOffset));
            CHECK(accessUnit->meta()->findInt32("rangeLength", &rangeLength));
            CHECK(accessUnit->meta()->findMessage("notify", &notify)
                    && notify != NULL);
            CHECK_GE(accessUnit->size(), rangeLength);

            sp<GraphicBuffer> grbuf(new GraphicBuffer(
                    rangeOffset + rangeLength, 1, HAL_PIXEL_FORMAT_Y8,
                    GRALLOC_USAGE_HW_VIDEO_ENCODER, rangeOffset + rangeLength,
                    handle, false));

            err = mHDCP->encryptNative(
                    grbuf, rangeOffset, rangeLength,
                    trackIndex  /* streamCTR */,
                    &inputCTR,
                    accessUnit->data());
            notify->post();
        } else {
            err = mHDCP->encrypt(
                    accessUnit->data(), accessUnit->size(),
                    trackIndex  /* streamCTR */,
                    &inputCTR,
                    accessUnit->data());
        }

        if (err != OK) {
            ALOGE("Failed to HDCP-encrypt media data (err %d)",
                  err);

            return err;
        }

        HDCP_private_data[0] = 0x00;

        HDCP_private_data[1] =
            (((trackIndex >> 30) & 3) << 1) | 1;

        HDCP_private_data[2] = (trackIndex >> 22) & 0xff;

        HDCP_private_data[3] =
            (((trackIndex >> 15) & 0x7f) << 1) | 1;

        HDCP_private_data[4] = (trackIndex >> 7) & 0xff;

        HDCP_private_data[5] =
            ((trackIndex & 0x7f) << 1) | 1;

        HDCP_private_data[6] = 0x00;

        HDCP_private_data[7] =
            (((inputCTR >> 60) & 0x0f) << 1) | 1;

        HDCP_private_data[8] = (inputCTR >> 52) & 0xff;

        HDCP_private_data[9] =
            (((inputCTR >> 45) & 0x7f) << 1) | 1;

        HDCP_private_data[10] = (inputCTR >> 37) & 0xff;

        HDCP_private_data[11] =
            (((inputCTR >> 30) & 0x7f) << 1) | 1;

        HDCP_private_data[12] = (inputCTR >> 22) & 0xff;

        HDCP_private_data[13] =
            (((inputCTR >> 15) & 0x7f) << 1) | 1;

        HDCP_private_data[14] = (inputCTR >> 7) & 0xff;

        HDCP_private_data[15] =
            ((inputCTR & 0x7f) << 1) | 1;

        flags |= TSPacketizer::IS_ENCRYPTED;
    } else if (manuallyPrependSPSPPS) {
        flags |= TSPacketizer::PREPEND_SPS_PPS_TO_IDR_FRAMES;
    }

    int64_t timeUs = ALooper::GetNowUs();
    if (mPrevTimeUs < 0ll || mPrevTimeUs + 100000ll <= timeUs) {
        flags |= TSPacketizer::EMIT_PCR;
        flags |= TSPacketizer::EMIT_PAT_AND_PMT;

        mPrevTimeUs = timeUs;
    }

    mTSPacketizer->packetize(
            info.mPacketizerTrackIndex,
            accessUnit,
            tsPackets,
            flags,
            !isHDCPEncrypted ? NULL : HDCP_private_data,
            !isHDCPEncrypted ? 0 : sizeof(HDCP_private_data),
            info.mIsAudio ? 2 : 0 /* numStuffingBytes */);

    return OK;
}

}  // namespace android

