/*
 * Copyright (C) 2024 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 "../includes/common.h"

#include <C2AllocatorIon.h>
#include <C2BufferPriv.h>
#include <Codec2BufferUtils.h>
#include <Codec2Mapper.h>
#include <codec2/hidl/client.h>

#include "../includes/memutils.h"

char enable_selective_overload = ENABLE_NONE;

int main() {
  // Fetch graphic block
  std::shared_ptr<C2GraphicBlock> block;
  std::shared_ptr<C2AllocatorStore> store =
      android::GetCodec2PlatformAllocatorStore();
  std::shared_ptr<C2Allocator> graphicAllocator;
  store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &graphicAllocator);
  std::shared_ptr<C2BlockPool> graphicPool =
      std::make_shared<C2PooledBlockPool>(graphicAllocator, 0 /* id */);
  graphicPool->fetchGraphicBlock(
      MINIMUM_ALIGNMENT + 2 /* width */, 2 /* height */,
      HAL_PIXEL_FORMAT_YV12 /* pixel format */,
      {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
  FAIL_CHECK(block->map().get().layout().numPlanes == 3);

  // Get C2GraphicView object from block
  C2GraphicView view = block->map().get();

  // Set cropped dimension
  C2Rect crop = C2Rect(0 /* width */, 0 /* height */);
  view.setCrop_be(crop);
  std::vector<uint8_t> conversionBuffer;
  enable_selective_overload = ENABLE_ALL;
  conversionBuffer.resize(
      MINIMUM_ALIGNMENT); // as per MINIMUM_ALIGNMENT in memutils
  enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
  uint8_t *conversionBuff = (uint8_t *)conversionBuffer.data();

  // Without fix, block's width and height will be used for conversion. An OOB
  // write will occur when 16th index of the conversion buffer is accessed.
  // However with fix, 'crop width' and 'crop height' will be used for accessing
  // conversion buffer. Hence no OOB access is observed
  android::ConvertRGBToPlanarYUV(conversionBuff, 0 /* dstStride */,
                                 0 /* dstVstride */,
                                 MINIMUM_ALIGNMENT /* buffersize */, view);
}
