/*
 *  Copyright (c) 2011 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/media/engine/webrtcvideoframe.h"

#include "libyuv/convert.h"
#include "webrtc/base/logging.h"
#include "webrtc/media/base/videocapturer.h"
#include "webrtc/media/base/videocommon.h"
#include "webrtc/video_frame.h"

using webrtc::kYPlane;
using webrtc::kUPlane;
using webrtc::kVPlane;

namespace cricket {

WebRtcVideoFrame::WebRtcVideoFrame()
    : timestamp_us_(0), rotation_(webrtc::kVideoRotation_0) {}

WebRtcVideoFrame::WebRtcVideoFrame(
    const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer,
    webrtc::VideoRotation rotation,
    int64_t timestamp_us,
    uint32_t transport_frame_id)
    : video_frame_buffer_(buffer),
      timestamp_us_(timestamp_us),
      transport_frame_id_(transport_frame_id),
      rotation_(rotation) {}

WebRtcVideoFrame::WebRtcVideoFrame(
    const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer,
    webrtc::VideoRotation rotation,
    int64_t timestamp_us)
    : WebRtcVideoFrame(buffer, rotation, timestamp_us, 0) {};

WebRtcVideoFrame::WebRtcVideoFrame(
    const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer,
    int64_t time_stamp_ns,
    webrtc::VideoRotation rotation)
    : WebRtcVideoFrame(buffer,
                       rotation,
                       time_stamp_ns / rtc::kNumNanosecsPerMicrosec,
                       0) {}

WebRtcVideoFrame::~WebRtcVideoFrame() {}

bool WebRtcVideoFrame::Init(uint32_t format,
                            int w,
                            int h,
                            int dw,
                            int dh,
                            uint8_t* sample,
                            size_t sample_size,
                            int64_t time_stamp_ns,
                            webrtc::VideoRotation rotation) {
  return Reset(format, w, h, dw, dh, sample, sample_size,
               time_stamp_ns / rtc::kNumNanosecsPerMicrosec, rotation,
               true /*apply_rotation*/);
}

bool WebRtcVideoFrame::Init(const CapturedFrame* frame, int dw, int dh,
                            bool apply_rotation) {
  return Reset(frame->fourcc, frame->width, frame->height, dw, dh,
               static_cast<uint8_t*>(frame->data), frame->data_size,
               frame->time_stamp / rtc::kNumNanosecsPerMicrosec,
               frame->rotation, apply_rotation);
}

int WebRtcVideoFrame::width() const {
  return video_frame_buffer_ ? video_frame_buffer_->width() : 0;
}

int WebRtcVideoFrame::height() const {
  return video_frame_buffer_ ? video_frame_buffer_->height() : 0;
}

const rtc::scoped_refptr<webrtc::VideoFrameBuffer>&
WebRtcVideoFrame::video_frame_buffer() const {
  return video_frame_buffer_;
}

uint32_t WebRtcVideoFrame::transport_frame_id() const {
  return transport_frame_id_;
}

int64_t WebRtcVideoFrame::timestamp_us() const {
  return timestamp_us_;
}

void WebRtcVideoFrame::set_timestamp_us(int64_t time_us) {
  timestamp_us_ = time_us;
}

webrtc::VideoRotation WebRtcVideoFrame::rotation() const {
  return rotation_;
}

VideoFrame* WebRtcVideoFrame::Copy() const {
  return new WebRtcVideoFrame(video_frame_buffer_, rotation_, timestamp_us_,
                              transport_frame_id_);
}

size_t WebRtcVideoFrame::ConvertToRgbBuffer(uint32_t to_fourcc,
                                            uint8_t* buffer,
                                            size_t size,
                                            int stride_rgb) const {
  RTC_CHECK(video_frame_buffer_);
  RTC_CHECK(video_frame_buffer_->native_handle() == nullptr);
  return VideoFrame::ConvertToRgbBuffer(to_fourcc, buffer, size, stride_rgb);
}

bool WebRtcVideoFrame::Reset(uint32_t format,
                             int w,
                             int h,
                             int dw,
                             int dh,
                             uint8_t* sample,
                             size_t sample_size,
                             int64_t timestamp_us,
                             webrtc::VideoRotation rotation,
                             bool apply_rotation) {
  if (!Validate(format, w, h, sample, sample_size)) {
    return false;
  }
  // Translate aliases to standard enums (e.g., IYUV -> I420).
  format = CanonicalFourCC(format);

  // Set up a new buffer.
  // TODO(fbarchard): Support lazy allocation.
  int new_width = dw;
  int new_height = dh;
  // If rotated swap width, height.
  if (apply_rotation && (rotation == 90 || rotation == 270)) {
    new_width = dh;
    new_height = dw;
  }

  InitToEmptyBuffer(new_width, new_height);
  rotation_ = apply_rotation ? webrtc::kVideoRotation_0 : rotation;

  int horiz_crop = ((w - dw) / 2) & ~1;
  // ARGB on Windows has negative height.
  // The sample's layout in memory is normal, so just correct crop.
  int vert_crop = ((abs(h) - dh) / 2) & ~1;
  // Conversion functions expect negative height to flip the image.
  int idh = (h < 0) ? -dh : dh;
  int r = libyuv::ConvertToI420(
      sample, sample_size,
      video_frame_buffer_->MutableDataY(),
      video_frame_buffer_->StrideY(),
      video_frame_buffer_->MutableDataU(),
      video_frame_buffer_->StrideU(),
      video_frame_buffer_->MutableDataV(),
      video_frame_buffer_->StrideV(),
      horiz_crop, vert_crop,
      w, h,
      dw, idh,
      static_cast<libyuv::RotationMode>(
          apply_rotation ? rotation : webrtc::kVideoRotation_0),
      format);
  if (r) {
    LOG(LS_ERROR) << "Error parsing format: " << GetFourccName(format)
                  << " return code : " << r;
    return false;
  }
  timestamp_us_ = timestamp_us;
  return true;
}

void WebRtcVideoFrame::InitToEmptyBuffer(int w, int h) {
  video_frame_buffer_ = new rtc::RefCountedObject<webrtc::I420Buffer>(w, h);
  rotation_ = webrtc::kVideoRotation_0;
}

const VideoFrame* WebRtcVideoFrame::GetCopyWithRotationApplied() const {
  // If the frame is not rotated, the caller should reuse this frame instead of
  // making a redundant copy.
  if (rotation() == webrtc::kVideoRotation_0) {
    return this;
  }

  // If the video frame is backed up by a native handle, it resides in the GPU
  // memory which we can't rotate here. The assumption is that the renderers
  // which uses GPU to render should be able to rotate themselves.
  RTC_DCHECK(!video_frame_buffer()->native_handle());

  if (rotated_frame_) {
    return rotated_frame_.get();
  }

  int current_width = width();
  int current_height = height();

  int rotated_width = current_width;
  int rotated_height = current_height;
  if (rotation() == webrtc::kVideoRotation_90 ||
      rotation() == webrtc::kVideoRotation_270) {
    std::swap(rotated_width, rotated_height);
  }

  rtc::scoped_refptr<webrtc::I420Buffer> buffer =
      new rtc::RefCountedObject<webrtc::I420Buffer>(rotated_width,
                                                    rotated_height);

  // TODO(guoweis): Add a function in webrtc_libyuv.cc to convert from
  // VideoRotation to libyuv::RotationMode.
  int ret = libyuv::I420Rotate(
      video_frame_buffer_->DataY(), video_frame_buffer_->StrideY(),
      video_frame_buffer_->DataU(), video_frame_buffer_->StrideU(),
      video_frame_buffer_->DataV(), video_frame_buffer_->StrideV(),
      buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataU(),
      buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(),
      current_width, current_height,
      static_cast<libyuv::RotationMode>(rotation()));
  if (ret == 0) {
    rotated_frame_.reset(new WebRtcVideoFrame(
        buffer, webrtc::kVideoRotation_0, timestamp_us_, transport_frame_id_));
  }

  return rotated_frame_.get();
}

}  // namespace cricket
