/*
 *  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/video_frame.h"

#include <string.h>

#include <algorithm>  // swap

#include "webrtc/base/bind.h"
#include "webrtc/base/checks.h"

namespace webrtc {

// FFmpeg's decoder, used by H264DecoderImpl, requires up to 8 bytes padding due
// to optimized bitstream readers. See avcodec_decode_video2.
const size_t EncodedImage::kBufferPaddingBytesH264 = 8;

int ExpectedSize(int plane_stride, int image_height, PlaneType type) {
  if (type == kYPlane)
    return plane_stride * image_height;
  return plane_stride * ((image_height + 1) / 2);
}

VideoFrame::VideoFrame()
    : video_frame_buffer_(nullptr),
      timestamp_(0),
      ntp_time_ms_(0),
      render_time_ms_(0),
      rotation_(kVideoRotation_0) {}

VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
                       uint32_t timestamp,
                       int64_t render_time_ms,
                       VideoRotation rotation)
    : video_frame_buffer_(buffer),
      timestamp_(timestamp),
      ntp_time_ms_(0),
      render_time_ms_(render_time_ms),
      rotation_(rotation) {
  RTC_DCHECK(buffer);
}

void VideoFrame::CreateEmptyFrame(int width,
                                  int height,
                                  int stride_y,
                                  int stride_u,
                                  int stride_v) {
  const int half_width = (width + 1) / 2;
  RTC_DCHECK_GT(width, 0);
  RTC_DCHECK_GT(height, 0);
  RTC_DCHECK_GE(stride_y, width);
  RTC_DCHECK_GE(stride_u, half_width);
  RTC_DCHECK_GE(stride_v, half_width);

  // Creating empty frame - reset all values.
  timestamp_ = 0;
  ntp_time_ms_ = 0;
  render_time_ms_ = 0;
  rotation_ = kVideoRotation_0;

  // Allocate a new buffer.
  video_frame_buffer_ = new rtc::RefCountedObject<I420Buffer>(
      width, height, stride_y, stride_u, stride_v);
}

void VideoFrame::CreateFrame(const uint8_t* buffer_y,
                             const uint8_t* buffer_u,
                             const uint8_t* buffer_v,
                             int width,
                             int height,
                             int stride_y,
                             int stride_u,
                             int stride_v,
                             VideoRotation rotation) {
  const int half_height = (height + 1) / 2;
  const int expected_size_y = height * stride_y;
  const int expected_size_u = half_height * stride_u;
  const int expected_size_v = half_height * stride_v;
  CreateEmptyFrame(width, height, stride_y, stride_u, stride_v);
  memcpy(video_frame_buffer_->MutableDataY(), buffer_y, expected_size_y);
  memcpy(video_frame_buffer_->MutableDataU(), buffer_u, expected_size_u);
  memcpy(video_frame_buffer_->MutableDataV(), buffer_v, expected_size_v);
  rotation_ = rotation;
}

void VideoFrame::CreateFrame(const uint8_t* buffer,
                             int width,
                             int height,
                             VideoRotation rotation) {
  const int stride_y = width;
  const int stride_uv = (width + 1) / 2;

  const uint8_t* buffer_y = buffer;
  const uint8_t* buffer_u = buffer_y + stride_y * height;
  const uint8_t* buffer_v = buffer_u + stride_uv * ((height + 1) / 2);
  CreateFrame(buffer_y, buffer_u, buffer_v, width, height, stride_y,
              stride_uv, stride_uv, rotation);
}

void VideoFrame::CopyFrame(const VideoFrame& videoFrame) {
  ShallowCopy(videoFrame);

  // If backed by a plain memory buffer, create a new, non-shared, copy.
  if (video_frame_buffer_ && !video_frame_buffer_->native_handle()) {
    video_frame_buffer_ = I420Buffer::Copy(video_frame_buffer_);
  }
}

void VideoFrame::ShallowCopy(const VideoFrame& videoFrame) {
  video_frame_buffer_ = videoFrame.video_frame_buffer();
  timestamp_ = videoFrame.timestamp_;
  ntp_time_ms_ = videoFrame.ntp_time_ms_;
  render_time_ms_ = videoFrame.render_time_ms_;
  rotation_ = videoFrame.rotation_;
}

// TODO(nisse): Delete. Besides test code, only one use, in
// webrtcvideoengine2.cc:CreateBlackFrame.
int VideoFrame::allocated_size(PlaneType type) const {
  const int plane_height = (type == kYPlane) ? height() : (height() + 1) / 2;
  int stride;
  switch (type) {
    case kYPlane:
      stride = video_frame_buffer_->StrideY();
      break;
    case kUPlane:
      stride = video_frame_buffer_->StrideU();
      break;
    case kVPlane:
      stride = video_frame_buffer_->StrideV();
      break;
    default:
      RTC_NOTREACHED();
      return 0;
  }
  return plane_height * stride;
}

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

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

bool VideoFrame::IsZeroSize() const {
  return !video_frame_buffer_;
}

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

void VideoFrame::set_video_frame_buffer(
    const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer) {
  RTC_DCHECK(buffer);
  video_frame_buffer_ = buffer;
}

VideoFrame VideoFrame::ConvertNativeToI420Frame() const {
  RTC_DCHECK(video_frame_buffer_->native_handle());
  VideoFrame frame;
  frame.ShallowCopy(*this);
  frame.set_video_frame_buffer(video_frame_buffer_->NativeToI420Buffer());
  return frame;
}

size_t EncodedImage::GetBufferPaddingBytes(VideoCodecType codec_type) {
  switch (codec_type) {
    case kVideoCodecVP8:
    case kVideoCodecVP9:
      return 0;
    case kVideoCodecH264:
      return kBufferPaddingBytesH264;
    case kVideoCodecI420:
    case kVideoCodecRED:
    case kVideoCodecULPFEC:
    case kVideoCodecGeneric:
    case kVideoCodecUnknown:
      return 0;
  }
  RTC_NOTREACHED();
  return 0;
}

}  // namespace webrtc
