/*
 *  Copyright (c) 2012 The WebRTC 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 "webrtc/common_video/include/incoming_video_stream.h"

#include <assert.h>

#if defined(_WIN32)
#include <windows.h>
#elif defined(WEBRTC_LINUX)
#include <sys/time.h>
#include <time.h>
#else
#include <sys/time.h>
#endif

#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/common_video/video_render_frames.h"
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
#include "webrtc/system_wrappers/include/event_wrapper.h"
#include "webrtc/system_wrappers/include/thread_wrapper.h"
#include "webrtc/system_wrappers/include/tick_util.h"
#include "webrtc/system_wrappers/include/trace.h"

namespace webrtc {

IncomingVideoStream::IncomingVideoStream(uint32_t stream_id)
    : stream_id_(stream_id),
      stream_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
      thread_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
      buffer_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
      incoming_render_thread_(),
      deliver_buffer_event_(EventTimerWrapper::Create()),
      running_(false),
      external_callback_(nullptr),
      render_callback_(nullptr),
      render_buffers_(new VideoRenderFrames()),
      incoming_rate_(0),
      last_rate_calculation_time_ms_(0),
      num_frames_since_last_calculation_(0),
      last_render_time_ms_(0),
      temp_frame_(),
      start_image_(),
      timeout_image_(),
      timeout_time_() {
}

IncomingVideoStream::~IncomingVideoStream() {
  Stop();
}

VideoRenderCallback* IncomingVideoStream::ModuleCallback() {
  CriticalSectionScoped cs(stream_critsect_.get());
  return this;
}

int32_t IncomingVideoStream::RenderFrame(const uint32_t stream_id,
                                         const VideoFrame& video_frame) {
  CriticalSectionScoped csS(stream_critsect_.get());

  if (!running_) {
    return -1;
  }

  // Rate statistics.
  num_frames_since_last_calculation_++;
  int64_t now_ms = TickTime::MillisecondTimestamp();
  if (now_ms >= last_rate_calculation_time_ms_ + kFrameRatePeriodMs) {
    incoming_rate_ =
        static_cast<uint32_t>(1000 * num_frames_since_last_calculation_ /
                              (now_ms - last_rate_calculation_time_ms_));
    num_frames_since_last_calculation_ = 0;
    last_rate_calculation_time_ms_ = now_ms;
  }

  // Insert frame.
  CriticalSectionScoped csB(buffer_critsect_.get());
  if (render_buffers_->AddFrame(video_frame) == 1)
    deliver_buffer_event_->Set();

  return 0;
}

int32_t IncomingVideoStream::SetStartImage(const VideoFrame& video_frame) {
  CriticalSectionScoped csS(thread_critsect_.get());
  return start_image_.CopyFrame(video_frame);
}

int32_t IncomingVideoStream::SetTimeoutImage(const VideoFrame& video_frame,
                                             const uint32_t timeout) {
  CriticalSectionScoped csS(thread_critsect_.get());
  timeout_time_ = timeout;
  return timeout_image_.CopyFrame(video_frame);
}

void IncomingVideoStream::SetRenderCallback(
    VideoRenderCallback* render_callback) {
  CriticalSectionScoped cs(thread_critsect_.get());
  render_callback_ = render_callback;
}

int32_t IncomingVideoStream::SetExpectedRenderDelay(
    int32_t delay_ms) {
  CriticalSectionScoped csS(stream_critsect_.get());
  if (running_) {
    return -1;
  }
  CriticalSectionScoped cs(buffer_critsect_.get());
  return render_buffers_->SetRenderDelay(delay_ms);
}

void IncomingVideoStream::SetExternalCallback(
    VideoRenderCallback* external_callback) {
  CriticalSectionScoped cs(thread_critsect_.get());
  external_callback_ = external_callback;
}

int32_t IncomingVideoStream::Start() {
  CriticalSectionScoped csS(stream_critsect_.get());
  if (running_) {
    return 0;
  }

  CriticalSectionScoped csT(thread_critsect_.get());
  assert(incoming_render_thread_ == NULL);

  incoming_render_thread_ = ThreadWrapper::CreateThread(
      IncomingVideoStreamThreadFun, this, "IncomingVideoStreamThread");
  if (!incoming_render_thread_) {
    return -1;
  }

  if (incoming_render_thread_->Start()) {
  } else {
    return -1;
  }
  incoming_render_thread_->SetPriority(kRealtimePriority);
  deliver_buffer_event_->StartTimer(false, kEventStartupTimeMs);

  running_ = true;
  return 0;
}

int32_t IncomingVideoStream::Stop() {
  CriticalSectionScoped cs_stream(stream_critsect_.get());

  if (!running_) {
    return 0;
  }

  ThreadWrapper* thread = NULL;
  {
    CriticalSectionScoped cs_thread(thread_critsect_.get());
    if (incoming_render_thread_) {
      // Setting the incoming render thread to NULL marks that we're performing
      // a shutdown and will make IncomingVideoStreamProcess abort after wakeup.
      thread = incoming_render_thread_.release();
      deliver_buffer_event_->StopTimer();
      // Set the event to allow the thread to wake up and shut down without
      // waiting for a timeout.
      deliver_buffer_event_->Set();
    }
  }
  if (thread) {
    if (thread->Stop()) {
      delete thread;
    } else {
      assert(false);
    }
  }
  running_ = false;
  return 0;
}

int32_t IncomingVideoStream::Reset() {
  CriticalSectionScoped cs_buffer(buffer_critsect_.get());
  render_buffers_->ReleaseAllFrames();
  return 0;
}

uint32_t IncomingVideoStream::StreamId() const {
  return stream_id_;
}

uint32_t IncomingVideoStream::IncomingRate() const {
  CriticalSectionScoped cs(stream_critsect_.get());
  return incoming_rate_;
}

bool IncomingVideoStream::IncomingVideoStreamThreadFun(void* obj) {
  return static_cast<IncomingVideoStream*>(obj)->IncomingVideoStreamProcess();
}

bool IncomingVideoStream::IncomingVideoStreamProcess() {
  if (kEventError != deliver_buffer_event_->Wait(kEventMaxWaitTimeMs)) {
    CriticalSectionScoped cs(thread_critsect_.get());
    if (incoming_render_thread_ == NULL) {
      // Terminating
      return false;
    }
    // Get a new frame to render and the time for the frame after this one.
    VideoFrame frame_to_render;
    uint32_t wait_time;
    {
      CriticalSectionScoped cs(buffer_critsect_.get());
      frame_to_render = render_buffers_->FrameToRender();
      wait_time = render_buffers_->TimeToNextFrameRelease();
    }

    // Set timer for next frame to render.
    if (wait_time > kEventMaxWaitTimeMs) {
      wait_time = kEventMaxWaitTimeMs;
    }
    deliver_buffer_event_->StartTimer(false, wait_time);

    if (frame_to_render.IsZeroSize()) {
      if (render_callback_) {
        if (last_render_time_ms_ == 0 && !start_image_.IsZeroSize()) {
          // We have not rendered anything and have a start image.
          temp_frame_.CopyFrame(start_image_);
          render_callback_->RenderFrame(stream_id_, temp_frame_);
        } else if (!timeout_image_.IsZeroSize() &&
                   last_render_time_ms_ + timeout_time_ <
                       TickTime::MillisecondTimestamp()) {
          // Render a timeout image.
          temp_frame_.CopyFrame(timeout_image_);
          render_callback_->RenderFrame(stream_id_, temp_frame_);
        }
      }

      // No frame.
      return true;
    }

    // Send frame for rendering.
    if (external_callback_) {
      external_callback_->RenderFrame(stream_id_, frame_to_render);
    } else if (render_callback_) {
      render_callback_->RenderFrame(stream_id_, frame_to_render);
    }

    // We're done with this frame.
    if (!frame_to_render.IsZeroSize())
      last_render_time_ms_ = frame_to_render.render_time_ms();
  }
  return true;
}

}  // namespace webrtc
