/*
 *  Copyright 2017 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 "sdk/objc/Framework/Classes/VideoToolbox/objc_video_encoder_factory.h"

#include <string>

#import "NSString+StdString.h"
#import "RTCI420Buffer+Private.h"
#import "RTCVideoCodec+Private.h"
#import "WebRTC/RTCVideoCodec.h"
#import "WebRTC/RTCVideoCodecFactory.h"
#import "WebRTC/RTCVideoCodecH264.h"
#import "WebRTC/RTCVideoFrame.h"
#import "WebRTC/RTCVideoFrameBuffer.h"

#include "api/video/video_frame.h"
#include "api/video_codecs/video_encoder.h"
#include "modules/include/module_common_types.h"
#include "modules/video_coding/include/video_codec_interface.h"
#include "modules/video_coding/include/video_error_codes.h"
#include "rtc_base/logging.h"
#include "rtc_base/timeutils.h"
#include "sdk/objc/Framework/Classes/Common/helpers.h"
#include "sdk/objc/Framework/Classes/Video/objc_frame_buffer.h"

namespace webrtc {

namespace {

id<RTCVideoFrameBuffer> nativeToRtcFrameBuffer(const rtc::scoped_refptr<VideoFrameBuffer> &buffer) {
  return buffer->type() == VideoFrameBuffer::Type::kNative ?
      static_cast<ObjCFrameBuffer *>(buffer.get())->wrapped_frame_buffer() :
      [[RTCI420Buffer alloc] initWithFrameBuffer:buffer->ToI420()];
}

RTCVideoFrame *nativeToRtcFrame(const VideoFrame &frame) {
  RTCVideoFrame *rtcFrame =
      [[RTCVideoFrame alloc] initWithBuffer:nativeToRtcFrameBuffer(frame.video_frame_buffer())
                                   rotation:RTCVideoRotation(frame.rotation())
                                timeStampNs:frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec];
  rtcFrame.timeStamp = frame.timestamp();
  return rtcFrame;
}

class ObjCVideoEncoder : public VideoEncoder {
 public:
  ObjCVideoEncoder(id<RTCVideoEncoder> encoder)
      : encoder_(encoder), implementation_name_([encoder implementationName].stdString) {}

  int32_t InitEncode(const VideoCodec *codec_settings,
                     int32_t number_of_cores,
                     size_t max_payload_size) {
    RTCVideoEncoderSettings *settings =
        [[RTCVideoEncoderSettings alloc] initWithNativeVideoCodec:codec_settings];
    return [encoder_ startEncodeWithSettings:settings numberOfCores:number_of_cores];
  }

  int32_t RegisterEncodeCompleteCallback(EncodedImageCallback *callback) {
    [encoder_ setCallback:^BOOL(RTCEncodedImage *_Nonnull frame,
                                id<RTCCodecSpecificInfo> _Nonnull info,
                                RTCRtpFragmentationHeader *_Nonnull header) {
      EncodedImage encodedImage = [frame nativeEncodedImage];

      // Handle types than can be converted into one of CodecSpecificInfo's hard coded cases.
      CodecSpecificInfo codecSpecificInfo;
      if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
        codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info nativeCodecSpecificInfo];
      }

      std::unique_ptr<RTPFragmentationHeader> fragmentationHeader =
          [header createNativeFragmentationHeader];
      EncodedImageCallback::Result res =
          callback->OnEncodedImage(encodedImage, &codecSpecificInfo, fragmentationHeader.get());
      return res.error == EncodedImageCallback::Result::OK;
    }];

    return WEBRTC_VIDEO_CODEC_OK;
  }

  int32_t Release() { return [encoder_ releaseEncoder]; }

  int32_t Encode(const VideoFrame &frame,
                 const CodecSpecificInfo *codec_specific_info,
                 const std::vector<FrameType> *frame_types) {
    // CodecSpecificInfo only handles a hard coded list of codecs
    id<RTCCodecSpecificInfo> rtcCodecSpecificInfo = nil;
    if (codec_specific_info) {
      if (strcmp(codec_specific_info->codec_name, "H264") == 0) {
        RTCCodecSpecificInfoH264 *h264Info = [[RTCCodecSpecificInfoH264 alloc] init];
        h264Info.packetizationMode =
            (RTCH264PacketizationMode)codec_specific_info->codecSpecific.H264.packetization_mode;
        rtcCodecSpecificInfo = h264Info;
      }
    }

    NSMutableArray<NSNumber *> *rtcFrameTypes = [NSMutableArray array];
    for (size_t i = 0; i < frame_types->size(); ++i) {
      [rtcFrameTypes addObject:@(RTCFrameType(frame_types->at(i)))];
    }

    return [encoder_ encode:nativeToRtcFrame(frame)
          codecSpecificInfo:rtcCodecSpecificInfo
                 frameTypes:rtcFrameTypes];
  }

  int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) { return WEBRTC_VIDEO_CODEC_OK; }

  int32_t SetRates(uint32_t bitrate, uint32_t framerate) {
    return [encoder_ setBitrate:bitrate framerate:framerate];
  }

  bool SupportsNativeHandle() const { return true; }

  VideoEncoder::ScalingSettings GetScalingSettings() const {
    RTCVideoEncoderQpThresholds* qp_thresholds = [encoder_ scalingSettings];
    return qp_thresholds ?
        ScalingSettings(true /* enabled */, qp_thresholds.low, qp_thresholds.high) :
        ScalingSettings(false /* enabled */);
  }

  const char *ImplementationName() const { return implementation_name_.c_str(); }

 private:
  id<RTCVideoEncoder> encoder_;
  const std::string implementation_name_;
};
}  // namespace

ObjCVideoEncoderFactory::ObjCVideoEncoderFactory(id<RTCVideoEncoderFactory> encoder_factory)
    : encoder_factory_(encoder_factory) {}

ObjCVideoEncoderFactory::~ObjCVideoEncoderFactory() {}

id<RTCVideoEncoderFactory> ObjCVideoEncoderFactory::wrapped_encoder_factory() const {
  return encoder_factory_;
}

VideoEncoder *ObjCVideoEncoderFactory::CreateVideoEncoder(const cricket::VideoCodec &codec) {
  RTCVideoCodecInfo *info = [[RTCVideoCodecInfo alloc] initWithNativeVideoCodec:codec];
  id<RTCVideoEncoder> encoder = [encoder_factory_ createEncoder:info];
  return new ObjCVideoEncoder(encoder);
}

const std::vector<cricket::VideoCodec> &ObjCVideoEncoderFactory::supported_codecs() const {
  supported_codecs_.clear();
  for (RTCVideoCodecInfo *supportedCodec in encoder_factory_.supportedCodecs) {
    cricket::VideoCodec codec = [supportedCodec nativeVideoCodec];
    supported_codecs_.push_back(codec);
  }

  return supported_codecs_;
}

void ObjCVideoEncoderFactory::DestroyVideoEncoder(VideoEncoder *encoder) {
  delete encoder;
  encoder = nullptr;
}

}  // namespace webrtc
