// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// 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 "starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h"

#include <algorithm>
#include <deque>
#include <functional>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "starboard/common/condition_variable.h"
#include "starboard/common/mutex.h"
#include "starboard/common/scoped_ptr.h"
#include "starboard/common/string.h"
#include "starboard/common/time.h"
#include "starboard/configuration_constants.h"
#include "starboard/drm.h"
#include "starboard/media.h"
#include "starboard/memory.h"
#include "starboard/shared/starboard/media/media_util.h"
#include "starboard/shared/starboard/player/filter/player_components.h"
#include "starboard/shared/starboard/player/filter/stub_player_components_factory.h"
#include "starboard/shared/starboard/player/filter/testing/test_util.h"
#include "starboard/shared/starboard/player/job_queue.h"
#include "starboard/shared/starboard/player/video_dmp_reader.h"
#include "starboard/testing/fake_graphics_context_provider.h"
#include "starboard/thread.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace shared {
namespace starboard {
namespace player {
namespace filter {
namespace testing {
namespace {

using ::starboard::testing::FakeGraphicsContextProvider;
using ::std::placeholders::_1;
using ::std::placeholders::_2;
using video_dmp::VideoDmpReader;

}  // namespace

VideoDecoderTestFixture::VideoDecoderTestFixture(
    JobQueue* job_queue,
    FakeGraphicsContextProvider* fake_graphics_context_provider,
    const char* test_filename,
    SbPlayerOutputMode output_mode,
    bool using_stub_decoder)
    : job_queue_(job_queue),
      fake_graphics_context_provider_(fake_graphics_context_provider),
      test_filename_(test_filename),
      output_mode_(output_mode),
      using_stub_decoder_(using_stub_decoder),
      dmp_reader_(test_filename, VideoDmpReader::kEnableReadOnDemand) {
  SB_DCHECK(job_queue_);
  SB_DCHECK(fake_graphics_context_provider_);
  SB_LOG(INFO) << "Testing " << test_filename_ << ", output mode "
               << output_mode_
               << (using_stub_decoder_ ? " with stub video decoder." : ".");
}

void VideoDecoderTestFixture::Initialize() {
  ASSERT_NE(dmp_reader_.video_codec(), kSbMediaVideoCodecNone);
  ASSERT_GT(dmp_reader_.number_of_video_buffers(), 0);
  ASSERT_TRUE(GetVideoInputBuffer(0)->video_sample_info().is_key_frame);

  SbPlayerOutputMode output_mode = output_mode_;
  ASSERT_TRUE(PlayerComponents::Factory::OutputModeSupported(
      output_mode, dmp_reader_.video_codec(), kSbDrmSystemInvalid));
  int max_video_input_size = 0;

  PlayerComponents::Factory::CreationParameters creation_parameters(
      GetVideoInputBuffer(0)->video_stream_info(), &player_, output_mode,
      max_video_input_size,
      fake_graphics_context_provider_->decoder_target_provider(), nullptr);
  ASSERT_EQ(creation_parameters.max_video_input_size(), max_video_input_size);

  scoped_ptr<PlayerComponents::Factory> factory;
  if (using_stub_decoder_) {
    factory = StubPlayerComponentsFactory::Create();
  } else {
    factory = PlayerComponents::Factory::Create();
  }
  std::string error_message;
  ASSERT_TRUE(factory->CreateSubComponents(
      creation_parameters, nullptr, nullptr, &video_decoder_,
      &video_render_algorithm_, &video_renderer_sink_, &error_message));
  ASSERT_TRUE(video_decoder_);

  if (video_renderer_sink_) {
    video_renderer_sink_->SetRenderCB(
        std::bind(&VideoDecoderTestFixture::Render, this, _1));
  }

  video_decoder_->Initialize(
      std::bind(&VideoDecoderTestFixture::OnDecoderStatusUpdate, this, _1, _2),
      std::bind(&VideoDecoderTestFixture::OnError, this));
  if (HasPendingEvents()) {
    bool error_occurred = false;
    ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred));
    ASSERT_FALSE(error_occurred);
  }
}

void VideoDecoderTestFixture::OnDecoderStatusUpdate(
    VideoDecoder::Status status,
    const scoped_refptr<VideoFrame>& frame) {
  ScopedLock scoped_lock(mutex_);
  // TODO: Ensure that this is only called during dtor or Reset().
  if (status == VideoDecoder::kReleaseAllFrames) {
    SB_DCHECK(!frame);
    event_queue_.clear();
    decoded_frames_.clear();
    return;
  } else if (status == VideoDecoder::kNeedMoreInput) {
    event_queue_.push_back(Event(kNeedMoreInput, frame));
  } else if (status == VideoDecoder::kBufferFull) {
    event_queue_.push_back(Event(kBufferFull, frame));
  } else {
    event_queue_.push_back(Event(kError, frame));
    SB_LOG(WARNING) << "OnDecoderStatusUpdate received unknown state.";
  }
}

void VideoDecoderTestFixture::OnError() {
  ScopedLock scoped_lock(mutex_);
  event_queue_.push_back(Event(kError, NULL));
  SB_LOG(WARNING) << "Video decoder received error.";
}

void VideoDecoderTestFixture::AssertInvalidDecodeTarget() {
  if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
      !using_stub_decoder_) {
    volatile bool is_decode_target_valid = true;
    fake_graphics_context_provider_->RunOnGlesContextThread([&]() {
      SbDecodeTarget decode_target = video_decoder_->GetCurrentDecodeTarget();
      is_decode_target_valid = SbDecodeTargetIsValid(decode_target);
      SbDecodeTargetRelease(decode_target);
    });
    ASSERT_FALSE(is_decode_target_valid);
  }
}

void VideoDecoderTestFixture::WaitForNextEvent(Event* event, int64_t timeout) {
  ASSERT_TRUE(event);

  int64_t start = CurrentMonotonicTime();
  do {
    job_queue_->RunUntilIdle();
    GetDecodeTargetWhenSupported();
    {
      ScopedLock scoped_lock(mutex_);
      if (!event_queue_.empty()) {
        *event = event_queue_.front();
        event_queue_.pop_front();
        if (event->status == kNeedMoreInput) {
          need_more_input_ = true;
        } else if (event->status == kBufferFull) {
          if (!end_of_stream_written_) {
            ASSERT_FALSE(need_more_input_);
          }
        }
        return;
      }
    }
    SbThreadSleep(1000);
  } while (CurrentMonotonicTime() - start < timeout);
  event->status = kTimeout;
  SB_LOG(WARNING) << "WaitForNextEvent() timeout.";
}

bool VideoDecoderTestFixture::HasPendingEvents() {
  SbThreadSleep(5000);
  ScopedLock scoped_lock(mutex_);
  return !event_queue_.empty();
}

void VideoDecoderTestFixture::GetDecodeTargetWhenSupported() {
  if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
      !using_stub_decoder_) {
    fake_graphics_context_provider_->RunOnGlesContextThread([&]() {
      SbDecodeTargetRelease(video_decoder_->GetCurrentDecodeTarget());
    });
  }
}

void VideoDecoderTestFixture::AssertValidDecodeTargetWhenSupported() {
  volatile bool is_decode_target_valid = false;
  if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
      !using_stub_decoder_) {
    fake_graphics_context_provider_->RunOnGlesContextThread([&]() {
      SbDecodeTarget decode_target = video_decoder_->GetCurrentDecodeTarget();
      is_decode_target_valid = SbDecodeTargetIsValid(decode_target);
      SbDecodeTargetRelease(decode_target);
    });
    ASSERT_TRUE(is_decode_target_valid);
  }
}

// This has to be called when the decoder is just initialized/reset or when
// status is |kNeedMoreInput|.
void VideoDecoderTestFixture::WriteSingleInput(size_t index) {
  ASSERT_TRUE(need_more_input_);
  ASSERT_LT(index, dmp_reader_.number_of_video_buffers());

  auto input_buffer = GetVideoInputBuffer(index);
  {
    ScopedLock scoped_lock(mutex_);
    need_more_input_ = false;
    outstanding_inputs_.insert(input_buffer->timestamp());
  }
  video_decoder_->WriteInputBuffers({input_buffer});
}

void VideoDecoderTestFixture::WriteEndOfStream() {
  {
    ScopedLock scoped_lock(mutex_);
    end_of_stream_written_ = true;
  }
  video_decoder_->WriteEndOfStream();
}

void VideoDecoderTestFixture::WriteMultipleInputs(
    size_t start_index,
    size_t number_of_inputs_to_write,
    EventCB event_cb) {
  ASSERT_LE(start_index + number_of_inputs_to_write,
            dmp_reader_.number_of_video_buffers());

  ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index));
  ++start_index;
  --number_of_inputs_to_write;

  while (number_of_inputs_to_write > 0) {
    Event event;
    ASSERT_NO_FATAL_FAILURE(WaitForNextEvent(&event));
    if (event.status == kNeedMoreInput) {
      ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index));
      ++start_index;
      --number_of_inputs_to_write;
    } else if (event.status == kError || event.status == kTimeout) {
      // Assume that the caller doesn't expect an error when |event_cb| isn't
      // provided.
      ASSERT_TRUE(event_cb);
      bool continue_process = true;
      event_cb(event, &continue_process);
      ASSERT_FALSE(continue_process);
      return;
    } else {
      ASSERT_EQ(event.status, kBufferFull);
    }
    if (event.frame) {
      ASSERT_FALSE(event.frame->is_end_of_stream());
      if (!decoded_frames_.empty()) {
        ASSERT_LT(decoded_frames_.back()->timestamp(),
                  event.frame->timestamp());
      }
      decoded_frames_.push_back(event.frame);
      ASSERT_TRUE(AlmostEqualTime(*outstanding_inputs_.begin(),
                                  event.frame->timestamp()));
      outstanding_inputs_.erase(outstanding_inputs_.begin());
    }
    if (event_cb) {
      bool continue_process = true;
      event_cb(event, &continue_process);
      if (!continue_process) {
        return;
      }
    }
  }
}

void VideoDecoderTestFixture::DrainOutputs(bool* error_occurred,
                                           EventCB event_cb) {
  if (error_occurred) {
    *error_occurred = false;
  }

  bool end_of_stream_decoded = false;

  while (!end_of_stream_decoded) {
    Event event;
    ASSERT_NO_FATAL_FAILURE(WaitForNextEvent(&event));
    if (event.status == kError || event.status == kTimeout) {
      if (error_occurred) {
        *error_occurred = true;
      } else {
        FAIL();
      }
      return;
    }
    if (event.frame) {
      if (event.frame->is_end_of_stream()) {
        end_of_stream_decoded = true;
        if (!outstanding_inputs_.empty()) {
          SB_LOG(WARNING) << "|outstanding_inputs_| is not empty.";
          if (error_occurred) {
            *error_occurred = true;
          } else {
            // |error_occurred| is NULL indicates that the caller doesn't
            // expect an error, use the following redundant ASSERT to trigger
            // a failure.
            ASSERT_TRUE(outstanding_inputs_.empty());
          }
        }
      } else {
        if (!decoded_frames_.empty()) {
          ASSERT_LT(decoded_frames_.back()->timestamp(),
                    event.frame->timestamp());
        }
        decoded_frames_.push_back(event.frame);
        SB_DCHECK(!outstanding_inputs_.empty());
        ASSERT_TRUE(AlmostEqualTime(*outstanding_inputs_.begin(),
                                    event.frame->timestamp()));
        outstanding_inputs_.erase(outstanding_inputs_.begin());
      }
    }
    if (event_cb) {
      bool continue_process = true;
      event_cb(event, &continue_process);
      if (!continue_process) {
        return;
      }
    }
  }
}

void VideoDecoderTestFixture::ResetDecoderAndClearPendingEvents() {
  video_decoder_->Reset();
  ScopedLock scoped_lock(mutex_);
  event_queue_.clear();
  need_more_input_ = true;
  end_of_stream_written_ = false;
  outstanding_inputs_.clear();
  decoded_frames_.clear();
}

scoped_refptr<InputBuffer> VideoDecoderTestFixture::GetVideoInputBuffer(
    size_t index) {
  auto video_sample_info =
      dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeVideo, index);
  auto input_buffer =
      new InputBuffer(StubDeallocateSampleFunc, NULL, NULL, video_sample_info);
  auto iter = invalid_inputs_.find(index);
  if (iter != invalid_inputs_.end()) {
    std::vector<uint8_t> content(input_buffer->size(), iter->second);
    // Replace the content with invalid data.
    input_buffer->SetDecryptedContent(std::move(content));
  }
  return input_buffer;
}

}  // namespace testing
}  // namespace filter
}  // namespace player
}  // namespace starboard
}  // namespace shared
}  // namespace starboard
