// Copyright (C) 2020 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.

#include "host-common/MediaSnapshotHelper.h"
#include "host-common/H264NaluParser.h"
#include "host-common/VpxFrameParser.h"

#define MEDIA_SNAPSHOT_DEBUG 0

#if MEDIA_SNAPSHOT_DEBUG
#define SNAPSHOT_DPRINT(fmt, ...)                                       \
    fprintf(stderr, "media-snapshot-helper: %s:%d " fmt "\n", __func__, \
            __LINE__, ##__VA_ARGS__);
#else
#define SNAPSHOT_DPRINT(fmt, ...)
#endif

namespace android {
namespace emulation {

using PacketInfo = MediaSnapshotState::PacketInfo;
using ColorAspects = MediaSnapshotState::ColorAspects;

void MediaSnapshotHelper::savePacket(const uint8_t* frame,
                                     size_t szBytes,
                                     uint64_t inputPts) {
    if (mType == CodecType::H264) {
        return saveH264Packet(frame, szBytes, inputPts);
    } else {
        return saveVPXPacket(frame, szBytes, inputPts);
    }
}

void MediaSnapshotHelper::saveVPXPacket(const uint8_t* data,
                                        size_t len,
                                        uint64_t user_priv) {
    const bool enableSnapshot = true;
    if (enableSnapshot) {
        VpxFrameParser fparser(mType == CodecType::VP8 ? 8 : 9, data,
                               (size_t)len);
        SNAPSHOT_DPRINT("found frame type: %s frame",
                        fparser.isKeyFrame() ? "KEY" : "NON-KEY");
        std::vector<uint8_t> v;
        v.assign(data, data + len);
        bool isIFrame = fparser.isKeyFrame();
        if (isIFrame) {
            mSnapshotState.savedPackets.clear();
        }
        const bool saveOK = mSnapshotState.savePacket(v, user_priv);
        if (saveOK) {
            SNAPSHOT_DPRINT("saving packet of isze %d; total is %d",
                            (int)(v.size()),
                            (int)(mSnapshotState.savedPackets.size()));
        } else {
            SNAPSHOT_DPRINT("saving packet; has duplicate, skip; total is %d",
                            (int)(mSnapshotState.savedPackets.size()));
        }
    }
}

void MediaSnapshotHelper::saveH264Packet(const uint8_t* frame,
                                         size_t szBytes,
                                         uint64_t inputPts) {
    const bool enableSnapshot = true;
    if (enableSnapshot) {
        std::vector<uint8_t> v;
        v.assign(frame, frame + szBytes);
        bool hasSps = H264NaluParser::checkSpsFrame(frame, szBytes);
        if (hasSps) {
            SNAPSHOT_DPRINT("create new snapshot state");
            MediaSnapshotState newSnapshotState{};
            // we need to keep the frames, the guest might not have retrieved
            // them yet; otherwise, we might loose some frames
            std::swap(newSnapshotState.savedFrames, mSnapshotState.savedFrames);
            std::swap(newSnapshotState, mSnapshotState);
            mSnapshotState.saveSps(v);
        } else {
            bool hasPps = H264NaluParser::checkPpsFrame(frame, szBytes);
            if (hasPps) {
                mSnapshotState.savePps(v);
                mSnapshotState.savedPackets.clear();
                mSnapshotState.savedDecodedFrame.data.clear();
            } else {
                bool isIFrame = H264NaluParser::checkIFrame(frame, szBytes);
                if (isIFrame) {
                    mSnapshotState.savedPackets.clear();
                }
                mSnapshotState.savePacket(std::move(v), inputPts);
                SNAPSHOT_DPRINT("saving packet; total is %d",
                                (int)(mSnapshotState.savedPackets.size()));
            }
        }
    }
}
void MediaSnapshotHelper::save(base::Stream* stream) const {
    SNAPSHOT_DPRINT("saving packets now %d",
                    (int)(mSnapshotState.savedPackets.size()));
    if (mType == CodecType::H264) {
        stream->putBe32(264);
    } else if (mType == CodecType::VP8) {
        stream->putBe32(8);
    } else if (mType == CodecType::VP9) {
        stream->putBe32(9);
    }
    mSnapshotState.save(stream);
}

void MediaSnapshotHelper::replay(
        std::function<void(uint8_t* data, size_t len, uint64_t pts)>
                oneShotDecode) {
    if (mSnapshotState.sps.size() > 0) {
        oneShotDecode(mSnapshotState.sps.data(), mSnapshotState.sps.size(), 0);
        if (mSnapshotState.pps.size() > 0) {
            oneShotDecode(mSnapshotState.pps.data(), mSnapshotState.pps.size(),
                          0);
            for (int i = 0; i < mSnapshotState.savedPackets.size(); ++i) {
                MediaSnapshotState::PacketInfo& pkt =
                        mSnapshotState.savedPackets[i];
                SNAPSHOT_DPRINT("reloading frame %d size %d", i,
                                (int)pkt.data.size());
                oneShotDecode(pkt.data.data(), pkt.data.size(), pkt.pts);
            }
        }
    }
}

void MediaSnapshotHelper::load(
        base::Stream* stream,
        std::function<void(uint8_t* data, size_t len, uint64_t pts)>
                oneShotDecode) {
    int type = stream->getBe32();
    if (type == 264) {
        mType = CodecType::H264;
    } else if (type == 8) {
        mType = CodecType::VP8;
    } else if (type == 9) {
        mType = CodecType::VP9;
    }

    mSnapshotState.load(stream);

    SNAPSHOT_DPRINT("loaded packets %d, now restore decoder",
                    (int)(mSnapshotState.savedPackets.size()));

    replay(oneShotDecode);

    SNAPSHOT_DPRINT("Done loading snapshots frames\n\n");
}

}  // namespace emulation
}  // namespace android
