// 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 <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/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/stub_player_components_factory.h"
#include "starboard/shared/starboard/player/filter/testing/test_util.h"
#include "starboard/shared/starboard/player/filter/video_decoder_internal.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 "starboard/time.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_(ResolveTestFileName(test_filename).c_str()) {
  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(VideoDecoder::OutputModeSupported(
      output_mode, dmp_reader_.video_codec(), kSbDrmSystemInvalid));

  PlayerComponents::Factory::CreationParameters creation_parameters(
      dmp_reader_.video_codec(),
#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
      GetVideoInputBuffer(0)->video_sample_info(),
#endif  // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
      &player_, output_mode,
      fake_graphics_context_provider_->decoder_target_provider(), nullptr);

  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));
  }
}

void VideoDecoderTestFixture::OnError() {
  ScopedLock scoped_lock(mutex_);
  event_queue_.push_back(Event(kError, NULL));
}

#if SB_HAS(GLES2)
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);
  }
}
#endif  // SB_HAS(GLES2)

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

  SbTimeMonotonic start = SbTimeGetMonotonicNow();
  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(kSbTimeMillisecond);
  } while (SbTimeGetMonotonicNow() - start < timeout);
  event->status = kTimeout;
}

bool VideoDecoderTestFixture::HasPendingEvents() {
  const SbTime kDelay = 5 * kSbTimeMillisecond;
  SbThreadSleep(kDelay);
  ScopedLock scoped_lock(mutex_);
  return !event_queue_.empty();
}

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

void VideoDecoderTestFixture::AssertValidDecodeTargetWhenSupported() {
#if SB_HAS(GLES2)
  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);
  }
#endif  // SB_HAS(GLES2)
}

// This has to be called when the decoder is just initialized/reseted 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_->WriteInputBuffer(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 does'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);
        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) const {
  auto video_sample_info =
      dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeVideo, index);
#if SB_API_VERSION >= 11
  auto input_buffer =
      new InputBuffer(StubDeallocateSampleFunc, NULL, NULL, video_sample_info);
#else   // SB_API_VERSION >= 11
  auto input_buffer =
      new InputBuffer(kSbMediaTypeVideo, StubDeallocateSampleFunc, NULL, NULL,
                      video_sample_info, NULL);
#endif  // SB_API_VERSION >= 11
  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(content.data(),
                                      static_cast<int>(content.size()));
  }
  return input_buffer;
}

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