// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/gpu/test/video_decode_accelerator_unittest_helpers.h"

#include <utility>

#include "base/callback_helpers.h"
#include "base/files/file_util.h"
#include "base/strings/string_split.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/base/video_decoder_config.h"
#include "media/gpu/macros.h"
#include "media/gpu/test/rendering_helper.h"
#include "media/video/h264_parser.h"

#if defined(OS_CHROMEOS)
#include "ui/ozone/public/ozone_gpu_test_helper.h"
#endif

namespace media {
namespace test {

namespace {
const size_t kMD5StringLength = 32;
}  // namespace

VideoDecodeAcceleratorTestEnvironment::VideoDecodeAcceleratorTestEnvironment(
    bool use_gl_renderer)
    : use_gl_renderer_(use_gl_renderer),
      rendering_thread_("GLRenderingVDAClientThread") {}

VideoDecodeAcceleratorTestEnvironment::
    ~VideoDecodeAcceleratorTestEnvironment() {}

void VideoDecodeAcceleratorTestEnvironment::SetUp() {
  base::Thread::Options options;
  options.message_loop_type = base::MessageLoop::TYPE_UI;
  rendering_thread_.StartWithOptions(options);

  base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                           base::WaitableEvent::InitialState::NOT_SIGNALED);
  rendering_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&RenderingHelper::InitializeOneOff, use_gl_renderer_, &done));
  done.Wait();

#if defined(OS_CHROMEOS)
  gpu_helper_.reset(new ui::OzoneGpuTestHelper());
  // Need to initialize after the rendering side since the rendering side
  // initializes the "GPU" parts of Ozone.
  //
  // This also needs to be done in the test environment since this shouldn't
  // be initialized multiple times for the same Ozone platform.
  gpu_helper_->Initialize(base::ThreadTaskRunnerHandle::Get());
#endif
}

void VideoDecodeAcceleratorTestEnvironment::TearDown() {
#if defined(OS_CHROMEOS)
  gpu_helper_.reset();
#endif
  rendering_thread_.Stop();
}

scoped_refptr<base::SingleThreadTaskRunner>
VideoDecodeAcceleratorTestEnvironment::GetRenderingTaskRunner() const {
  return rendering_thread_.task_runner();
}

EncodedDataHelper::EncodedDataHelper(const std::string& data,
                                     VideoCodecProfile profile)
    : data_(data), profile_(profile) {}

EncodedDataHelper::EncodedDataHelper(const std::vector<uint8_t>& stream,
                                     VideoCodecProfile profile)
    : EncodedDataHelper(
          std::string(reinterpret_cast<const char*>(stream.data()),
                      stream.size()),
          profile) {}

EncodedDataHelper::~EncodedDataHelper() {
  base::STLClearObject(&data_);
}

bool EncodedDataHelper::IsNALHeader(const std::string& data, size_t pos) {
  return data[pos] == 0 && data[pos + 1] == 0 && data[pos + 2] == 0 &&
         data[pos + 3] == 1;
}

std::string EncodedDataHelper::GetBytesForNextData() {
  switch (VideoCodecProfileToVideoCodec(profile_)) {
    case kCodecH264:
      return GetBytesForNextFragment();
    case kCodecVP8:
    case kCodecVP9:
      return GetBytesForNextFrame();
    default:
      NOTREACHED();
      return std::string();
  }
}

std::string EncodedDataHelper::GetBytesForNextFragment() {
  if (next_pos_to_decode_ == 0) {
    size_t skipped_fragments_count = 0;
    if (!LookForSPS(&skipped_fragments_count)) {
      next_pos_to_decode_ = 0;
      return std::string();
    }
    num_skipped_fragments_ += skipped_fragments_count;
  }

  size_t start_pos = next_pos_to_decode_;
  size_t next_nalu_pos = GetBytesForNextNALU(start_pos);

  // Update next_pos_to_decode_.
  next_pos_to_decode_ = next_nalu_pos;
  return data_.substr(start_pos, next_nalu_pos - start_pos);
}

size_t EncodedDataHelper::GetBytesForNextNALU(size_t start_pos) {
  size_t pos = start_pos;
  if (pos + 4 > data_.size())
    return pos;
  LOG_ASSERT(IsNALHeader(data_, pos));
  pos += 4;
  while (pos + 4 <= data_.size() && !IsNALHeader(data_, pos)) {
    ++pos;
  }
  if (pos + 3 >= data_.size())
    pos = data_.size();
  return pos;
}

bool EncodedDataHelper::LookForSPS(size_t* skipped_fragments_count) {
  *skipped_fragments_count = 0;
  while (next_pos_to_decode_ + 4 < data_.size()) {
    if ((data_[next_pos_to_decode_ + 4] & 0x1f) == 0x7) {
      return true;
    }
    *skipped_fragments_count += 1;
    next_pos_to_decode_ = GetBytesForNextNALU(next_pos_to_decode_);
  }
  return false;
}

std::string EncodedDataHelper::GetBytesForNextFrame() {
  // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF
  size_t pos = next_pos_to_decode_;
  std::string bytes;
  if (pos == 0)
    pos = 32;  // Skip IVF header.

  uint32_t frame_size = *reinterpret_cast<uint32_t*>(&data_[pos]);
  pos += 12;  // Skip frame header.
  bytes.append(data_.substr(pos, frame_size));

  // Update next_pos_to_decode_.
  next_pos_to_decode_ = pos + frame_size;
  return bytes;
}

// static
bool EncodedDataHelper::HasConfigInfo(const uint8_t* data,
                                      size_t size,
                                      VideoCodecProfile profile) {
  if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
    H264Parser parser;
    parser.SetStream(data, size);
    H264NALU nalu;
    H264Parser::Result result = parser.AdvanceToNextNALU(&nalu);
    if (result != H264Parser::kOk) {
      // Let the VDA figure out there's something wrong with the stream.
      return false;
    }

    return nalu.nal_unit_type == H264NALU::kSPS;
  } else if (profile >= VP8PROFILE_MIN && profile <= VP9PROFILE_MAX) {
    return (size > 0 && !(data[0] & 0x01));
  }
  // Shouldn't happen at this point.
  LOG(FATAL) << "Invalid profile: " << GetProfileName(profile);
  return false;
}

// Read in golden MD5s for the thumbnailed rendering of this video
std::vector<std::string> ReadGoldenThumbnailMD5s(
    const base::FilePath& md5_file_path) {
  std::vector<std::string> golden_md5s;
  std::vector<std::string> md5_strings;
  std::string all_md5s;
  base::ReadFileToString(md5_file_path, &all_md5s);
  md5_strings = base::SplitString(all_md5s, "\n", base::TRIM_WHITESPACE,
                                  base::SPLIT_WANT_ALL);
  // Check these are legitimate MD5s.
  for (const std::string& md5_string : md5_strings) {
    // Ignore the empty string added by SplitString
    if (!md5_string.length())
      continue;
    // Ignore comments
    if (md5_string.at(0) == '#')
      continue;

    bool valid_length = md5_string.length() == kMD5StringLength;
    LOG_IF(ERROR, !valid_length) << "MD5 length error: " << md5_string;
    bool hex_only = std::count_if(md5_string.begin(), md5_string.end(),
                                  isxdigit) == kMD5StringLength;
    LOG_IF(ERROR, !hex_only) << "MD5 includes non-hex char: " << md5_string;
    if (valid_length && hex_only)
      golden_md5s.push_back(md5_string);
  }
  LOG_IF(ERROR, md5_strings.empty())
      << "  MD5 checksum file (" << md5_file_path.MaybeAsASCII()
      << ") missing or empty.";
  return golden_md5s;
}

bool ConvertRGBAToRGB(const std::vector<unsigned char>& rgba,
                      std::vector<unsigned char>* rgb) {
  size_t num_pixels = rgba.size() / 4;
  rgb->resize(num_pixels * 3);
  // Drop the alpha channel, but check as we go that it is all 0xff.
  bool solid = true;
  for (size_t i = 0; i < num_pixels; i++) {
    (*rgb)[3 * i] = rgba[4 * i];
    (*rgb)[3 * i + 1] = rgba[4 * i + 1];
    (*rgb)[3 * i + 2] = rgba[4 * i + 2];
    solid = solid && (rgba[4 * i + 3] == 0xff);
  }
  return solid;
}
}  // namespace test
}  // namespace media
