// 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.
//
//
// frame parsing code is taken from libvpx decoder
/*
 *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "host-common/VpxFrameParser.h"

#define VPX_DEBUG 0

#if VPX_DEBUG
#define RED "\x1B[31m"
#define GRN "\x1B[32m"
#define YEL "\x1B[33m"
#define BLU "\x1B[34m"
#define MAG "\x1B[35m"
#define CYN "\x1B[36m"
#define WHT "\x1B[37m"
#define RESET "\x1B[0m"
#define VPX_PRINT(color, fmt, ...)                                           \
    fprintf(stderr, color "VpxFrameParser: %s:%d " fmt "\n" RESET, __func__, \
            __LINE__, ##__VA_ARGS__);
#else
#define VPX_PRINT(fmt, ...)
#endif

#define VPX_INFO(fmt, ...) VPX_PRINT(RESET, fmt, ##__VA_ARGS__);
#define VPX_WARN(fmt, ...) VPX_PRINT(YEL, fmt, ##__VA_ARGS__);
#define VPX_ERROR(fmt, ...) VPX_PRINT(RED, fmt, ##__VA_ARGS__);

namespace android {
namespace emulation {

VpxFrameParser::VpxFrameParser(int vpxtype, const uint8_t* data, size_t size)
    : type(vpxtype), bit_buffer(data), bit_buffer_end(data + size) {
    if (vpxtype == 8) {
        parse_vp8_uncompressed_header();
    } else if (vpxtype == 9) {
        parse_vp9_uncompressed_header();
    }
}

int VpxFrameParser::read_bit() {
    const size_t off = bit_offset;
    const size_t p = off >> 3;
    const int q = 7 - (int)(off & 0x7);
    if (bit_buffer + p < bit_buffer_end) {
        const int bit = (bit_buffer[p] >> q) & 1;
        bit_offset = off + 1;
        return bit;
    } else {
        return 0;
    }
}

int VpxFrameParser::read_literal(int bits) {
    int value = 0, bit;
    for (bit = bits - 1; bit >= 0; bit--)
        value |= read_bit() << bit;
    return value;
}

void VpxFrameParser::parse_vp9_uncompressed_header() {
    // http://downloads.webmproject.org/docs/vp9/vp9-bitstream_superframe-and-uncompressed-header_v1.0.pdf
    // FRAME_MARKER 2bits
    // version 1 bit
    // high 1 bit
    // profile = high << 1 + version
    // optional 1 bit
    // show_existing_frame 1 bit
    // optional 3 bit
    // frame_tyep 1 bit

    read_literal(2);
    int profile = read_bit();
    profile |= read_bit() << 1;
    if (profile > 2)
        profile += read_bit();
    int show_existing_frame = read_bit();
    if (show_existing_frame) {
        read_literal(3);
    }
    m_is_key_frame = (read_bit() == KEY_FRAME);
    VPX_PRINT("found vp9 %s frame", m_is_key_frame ? "KEY" : "NON-KEY");
}

void VpxFrameParser::parse_vp8_uncompressed_header() {
    // https://tools.ietf.org/html/rfc6386#section-9.1
    m_is_key_frame = (read_bit() == KEY_FRAME);
    VPX_PRINT("found vp8 %s frame", m_is_key_frame ? "KEY" : "NON-KEY");
}

}  // namespace emulation
}  // namespace android