// Copyright 2014 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 "remoting/client/software_video_renderer.h"

#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "remoting/base/util.h"
#include "remoting/codec/video_decoder.h"
#include "remoting/codec/video_decoder_verbatim.h"
#include "remoting/codec/video_decoder_vpx.h"
#include "remoting/proto/video.pb.h"
#include "remoting/protocol/frame_consumer.h"
#include "remoting/protocol/session_config.h"
#include "third_party/libyuv/include/libyuv/convert_argb.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"

using remoting::protocol::ChannelConfig;
using remoting::protocol::SessionConfig;

namespace remoting {

namespace {

// This class wraps a VideoDecoder and byte-swaps the pixels for compatibility
// with the android.graphics.Bitmap class.
// TODO(lambroslambrou): Refactor so that the VideoDecoder produces data
// in the right byte-order, instead of swapping it here.
class RgbToBgrVideoDecoderFilter : public VideoDecoder {
 public:
  RgbToBgrVideoDecoderFilter(scoped_ptr<VideoDecoder> parent)
      : parent_(std::move(parent)) {}

  bool DecodePacket(const VideoPacket& packet,
                    webrtc::DesktopFrame* frame) override {
    if (!parent_->DecodePacket(packet, frame))
      return false;
    for (webrtc::DesktopRegion::Iterator i(frame->updated_region());
         !i.IsAtEnd(); i.Advance()) {
      webrtc::DesktopRect rect = i.rect();
      uint8_t* pixels = frame->data() + (rect.top() * frame->stride()) +
                        (rect.left() * webrtc::DesktopFrame::kBytesPerPixel);
      libyuv::ABGRToARGB(pixels, frame->stride(), pixels, frame->stride(),
                         rect.width(), rect.height());
    }

    return true;
  }

 private:
  scoped_ptr<VideoDecoder> parent_;
};

scoped_ptr<webrtc::DesktopFrame> DoDecodeFrame(
    VideoDecoder* decoder,
    scoped_ptr<VideoPacket> packet,
    scoped_ptr<webrtc::DesktopFrame> frame) {
  if (!decoder->DecodePacket(*packet, frame.get()))
    frame.reset();
  return frame;
}

}  // namespace

SoftwareVideoRenderer::SoftwareVideoRenderer(
    scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner,
    protocol::FrameConsumer* consumer,
    protocol::PerformanceTracker* perf_tracker)
    : decode_task_runner_(decode_task_runner),
      consumer_(consumer),
      perf_tracker_(perf_tracker),
      weak_factory_(this) {}

SoftwareVideoRenderer::~SoftwareVideoRenderer() {
  if (decoder_)
    decode_task_runner_->DeleteSoon(FROM_HERE, decoder_.release());
}

void SoftwareVideoRenderer::OnSessionConfig(
    const protocol::SessionConfig& config) {
  DCHECK(thread_checker_.CalledOnValidThread());

  // Initialize decoder based on the selected codec.
  ChannelConfig::Codec codec = config.video_config().codec;
  if (codec == ChannelConfig::CODEC_VERBATIM) {
    decoder_.reset(new VideoDecoderVerbatim());
  } else if (codec == ChannelConfig::CODEC_VP8) {
    decoder_ = VideoDecoderVpx::CreateForVP8();
  } else if (codec == ChannelConfig::CODEC_VP9) {
    decoder_ = VideoDecoderVpx::CreateForVP9();
  } else {
    NOTREACHED() << "Invalid Encoding found: " << codec;
  }

  if (consumer_->GetPixelFormat() == protocol::FrameConsumer::FORMAT_RGBA) {
    decoder_ =
        make_scoped_ptr(new RgbToBgrVideoDecoderFilter(std::move(decoder_)));
  }
}

protocol::VideoStub* SoftwareVideoRenderer::GetVideoStub() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return this;
}

protocol::FrameConsumer* SoftwareVideoRenderer::GetFrameConsumer() {
  return consumer_;
}

void SoftwareVideoRenderer::ProcessVideoPacket(scoped_ptr<VideoPacket> packet,
                                               const base::Closure& done) {
  DCHECK(thread_checker_.CalledOnValidThread());

  base::ScopedClosureRunner done_runner(done);

  if (perf_tracker_)
    perf_tracker_->RecordVideoPacketStats(*packet);

  // If the video packet is empty then drop it. Empty packets are used to
  // maintain activity on the network.
  if (!packet->has_data() || packet->data().size() == 0) {
    return;
  }

  if (packet->format().has_screen_width() &&
      packet->format().has_screen_height()) {
    source_size_.set(packet->format().screen_width(),
                     packet->format().screen_height());
  }

  if (packet->format().has_x_dpi() && packet->format().has_y_dpi()) {
    webrtc::DesktopVector source_dpi(packet->format().x_dpi(),
                                     packet->format().y_dpi());
    if (!source_dpi.equals(source_dpi_)) {
      source_dpi_ = source_dpi;
    }
  }

  if (source_size_.is_empty()) {
    LOG(ERROR) << "Received VideoPacket with unknown size.";
    return;
  }

  scoped_ptr<webrtc::DesktopFrame> frame =
      consumer_->AllocateFrame(source_size_);
  frame->set_dpi(source_dpi_);

  int32_t frame_id = packet->frame_id();
  base::PostTaskAndReplyWithResult(
      decode_task_runner_.get(), FROM_HERE,
      base::Bind(&DoDecodeFrame, decoder_.get(), base::Passed(&packet),
                 base::Passed(&frame)),
      base::Bind(&SoftwareVideoRenderer::RenderFrame,
                 weak_factory_.GetWeakPtr(), frame_id, done_runner.Release()));
}

void SoftwareVideoRenderer::RenderFrame(
    int32_t frame_id,
    const base::Closure& done,
    scoped_ptr<webrtc::DesktopFrame> frame) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (perf_tracker_)
    perf_tracker_->OnFrameDecoded(frame_id);

  if (!frame) {
    if (!done.is_null())
      done.Run();
    return;
  }

  consumer_->DrawFrame(std::move(frame),
                       base::Bind(&SoftwareVideoRenderer::OnFrameRendered,
                                  weak_factory_.GetWeakPtr(), frame_id, done));
}

void SoftwareVideoRenderer::OnFrameRendered(int32_t frame_id,
                                            const base::Closure& done) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (perf_tracker_)
    perf_tracker_->OnFramePainted(frame_id);

  if (!done.is_null())
    done.Run();
}

}  // namespace remoting
