/*
 *  Copyright (c) 2013 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.
 */

// This file contains JNI for the video engine interfaces.
// The native functions are found using jni's auto discovery.

#include "webrtc/examples/android/media_demo/jni/video_engine_jni.h"

#include <map>
#include <string>

#include "webrtc/base/arraysize.h"
#include "webrtc/common_types.h"
#include "webrtc/examples/android/media_demo/jni/jni_helpers.h"
#include "webrtc/examples/android/media_demo/jni/media_codec_video_decoder.h"
#include "webrtc/examples/android/media_demo/jni/voice_engine_jni.h"
#include "webrtc/modules/utility/interface/helpers_android.h"
#include "webrtc/test/channel_transport/include/channel_transport.h"
#include "webrtc/video_engine/include/vie_base.h"
#include "webrtc/video_engine/include/vie_capture.h"
#include "webrtc/video_engine/include/vie_codec.h"
#include "webrtc/video_engine/include/vie_external_codec.h"
#include "webrtc/video_engine/include/vie_network.h"
#include "webrtc/video_engine/include/vie_render.h"
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"

// Macro for native functions that can be found by way of jni-auto discovery.
// Note extern "C" is needed for "discovery" of native methods to work.
#define JOWW(rettype, name)                                             \
  extern "C" rettype JNIEXPORT JNICALL Java_org_webrtc_webrtcdemo_##name

namespace {

static JavaVM* g_vm = NULL;
static ClassReferenceHolder* g_class_reference_holder = NULL;

jclass GetClass(const char* name) {
  CHECK(g_class_reference_holder, "Class reference holder NULL");
  return g_class_reference_holder->GetClass(name);
}

// C(++) description of a camera. This class is created by Java native calls
// and associated with the CameraDesc Java class. The Java class is used in the
// Java code but it is just a thin wrapper of the C(++) class that contain the
// actual information. The information is stored in C(++) as it is used to
// call video engine APIs.
struct CameraDesc {
  // The name and id corresponds to ViECapture's |device_nameUTF8| and
  // |unique_idUTF8|.
  char name[64];
  char unique_id[64];
};

// C++ callback class that can be used to register for callbacks from the
// video engine. It further propagates the callbacks to
// VideoDecodeEncodeObserver.java interface. The memory associated with this
// class is managed globally by the VideoEngineData class when registering and
// unregistering VideoDecodeEncodeObserver.java to receive callbacks.
class VideoDecodeEncodeObserver : public webrtc::ViEDecoderObserver,
                                  public webrtc::ViEEncoderObserver {
 public:
  explicit VideoDecodeEncodeObserver(jobject j_observer)
      : j_observer_(j_observer) {
    webrtc::AttachThreadScoped ats(g_vm);
    JNIEnv* jni = ats.env();
    jclass j_observer_class = jni->GetObjectClass(j_observer_);
    incoming_rate_ =
        GetMethodID(jni, j_observer_class, "incomingRate", "(III)V");
    incoming_codec_changed_ =
        GetMethodID(jni, j_observer_class, "incomingCodecChanged",
                    "(ILorg/webrtc/webrtcdemo/VideoCodecInst;)V");
    request_new_keyframe_ =
        GetMethodID(jni, j_observer_class, "requestNewKeyFrame", "(I)V");
    outgoing_rate_ =
        GetMethodID(jni, j_observer_class, "outgoingRate", "(III)V");
    j_observer_ = jni->NewGlobalRef(j_observer_);
  }

  ~VideoDecodeEncodeObserver() {
    webrtc::AttachThreadScoped ats(g_vm);
    JNIEnv* jni = ats.env();
    jni->DeleteGlobalRef(j_observer_);
  }

  virtual void IncomingRate(const int video_channel,
                            const unsigned int framerate,
                            const unsigned int bitrate) {
    webrtc::AttachThreadScoped ats(g_vm);
    JNIEnv* jni = ats.env();
    jni->CallVoidMethod(j_observer_, incoming_rate_, video_channel,
                        static_cast<int>(framerate), static_cast<int>(bitrate));
  }

  virtual void DecoderTiming(int decode_ms, int max_decode_ms,
                             int current_delay_ms, int target_delay_ms,
                             int jitter_buffer_ms, int min_playout_delay_ms,
                             int render_delay_ms) {
    // TODO(fischman): consider plumbing this through to Java.
  }

  virtual void IncomingCodecChanged(const int video_channel,
                                    const webrtc::VideoCodec& video_codec) {
    webrtc::AttachThreadScoped ats(g_vm);
    JNIEnv* jni = ats.env();
    webrtc::VideoCodec* codec = new webrtc::VideoCodec(video_codec);
    jclass j_codec_class =
        GetClass("org/webrtc/webrtcdemo/VideoCodecInst");
    jmethodID j_codec_ctor = GetMethodID(jni, j_codec_class, "<init>", "(J)V");
    jobject j_codec =
        jni->NewObject(j_codec_class, j_codec_ctor, jlongFromPointer(codec));
    CHECK_JNI_EXCEPTION(jni, "error during NewObject");
    jni->CallVoidMethod(j_observer_, incoming_codec_changed_, video_channel,
                        j_codec);
  }

  virtual void RequestNewKeyFrame(const int video_channel) {
    webrtc::AttachThreadScoped ats(g_vm);
    JNIEnv* jni = ats.env();
    jni->CallVoidMethod(j_observer_, request_new_keyframe_, video_channel);
  }

  virtual void OutgoingRate(const int video_channel,
                            const unsigned int framerate,
                            const unsigned int bitrate) {
    webrtc::AttachThreadScoped ats(g_vm);
    JNIEnv* jni = ats.env();
    jni->CallVoidMethod(j_observer_, outgoing_rate_, video_channel,
                        static_cast<int>(framerate), static_cast<int>(bitrate));
  }

  virtual void SuspendChange(int video_channel, bool is_suspended) {}

 private:
  jobject j_observer_;
  jmethodID incoming_rate_;
  jmethodID incoming_codec_changed_;
  jmethodID request_new_keyframe_;
  jmethodID outgoing_rate_;
};

template<typename T>
void ReleaseSubApi(T instance) {
  CHECK(instance->Release() == 0, "failed to release instance")
}

class VideoEngineData {
 public:
  VideoEngineData()
      : vie(webrtc::VideoEngine::Create()),
        base(webrtc::ViEBase::GetInterface(vie)),
        codec(webrtc::ViECodec::GetInterface(vie)),
        network(webrtc::ViENetwork::GetInterface(vie)),
        rtp(webrtc::ViERTP_RTCP::GetInterface(vie)),
        render(webrtc::ViERender::GetInterface(vie)),
        capture(webrtc::ViECapture::GetInterface(vie)),
        externalCodec(webrtc::ViEExternalCodec::GetInterface(vie)) {
    CHECK(vie != NULL, "Video engine instance failed to be created");
    CHECK(base != NULL, "Failed to acquire base interface");
    CHECK(codec != NULL, "Failed to acquire codec interface");
    CHECK(network != NULL, "Failed to acquire network interface");
    CHECK(rtp != NULL, "Failed to acquire rtp interface");
    CHECK(render != NULL, "Failed to acquire render interface");
    CHECK(capture != NULL, "Failed to acquire capture interface");
    CHECK(externalCodec != NULL, "Failed to acquire externalCodec interface");
  }

  ~VideoEngineData() {
    CHECK(channel_transports_.empty(),
          "ViE transports must be deleted before terminating");
    CHECK(observers_.empty(),
          "ViE observers must be deleted before terminating");
    CHECK(external_decoders_.empty(),
          "ViE external decoders must be deleted before terminating");
    ReleaseSubApi(externalCodec);
    ReleaseSubApi(capture);
    ReleaseSubApi(render);
    ReleaseSubApi(rtp);
    ReleaseSubApi(network);
    ReleaseSubApi(codec);
    ReleaseSubApi(base);
    webrtc::VideoEngine* vie_pointer = vie;
    CHECK(webrtc::VideoEngine::Delete(vie_pointer), "ViE failed to be deleted");
  }

  int CreateChannel() {
    int channel;
    CHECK(base->CreateChannel(channel) == 0, "Failed to create channel");
    CreateTransport(channel);
    return channel;
  }

  int DeleteChannel(int channel) {
    if (base->DeleteChannel(channel) != 0) {
      return -1;
    }
    DeleteTransport(channel);
    return 0;
  }

  webrtc::test::VideoChannelTransport* GetTransport(int channel) {
    ChannelTransports::iterator found = channel_transports_.find(channel);
    if (found == channel_transports_.end()) {
      return NULL;
    }
    return found->second;
  }

  int RegisterObserver(int channel, jobject j_observer) {
    CHECK(observers_.find(channel) == observers_.end(),
          "Observer already created for channel, inconsistent state");
    observers_[channel] = new VideoDecodeEncodeObserver(j_observer);
    int ret_val = codec->RegisterDecoderObserver(channel, *observers_[channel]);
    ret_val |= codec->RegisterEncoderObserver(channel, *observers_[channel]);
    return ret_val;
  }

  int DeregisterObserver(int channel) {
    Observers::iterator found = observers_.find(channel);
    if (observers_.find(channel) == observers_.end()) {
      return -1;
    }
    int ret_val = codec->DeregisterDecoderObserver(channel);
    ret_val |= codec->DeregisterEncoderObserver(channel);
    delete found->second;
    observers_.erase(found);
    return ret_val;
  }

  int RegisterExternalReceiveCodec(jint channel, jint pl_type, jobject decoder,
                                   bool internal_source) {
    CHECK(external_decoders_.find(channel) == external_decoders_.end(),
          "External decoder already created for channel, inconsistent state");
    external_decoders_[channel] =
        new webrtc::MediaCodecVideoDecoder(g_vm, decoder);
    return externalCodec->RegisterExternalReceiveCodec(
        channel, pl_type, external_decoders_[channel], internal_source);
  }

  int DeRegisterExternalReceiveCodec(jint channel, jint pl_type) {
    ExternalDecoders::iterator found = external_decoders_.find(channel);
    CHECK(found != external_decoders_.end(),
          "ViE channel missing external decoder, inconsistent state");
    CHECK(externalCodec->DeRegisterExternalReceiveCodec(channel, pl_type) == 0,
          "Failed to register external receive decoder");
    delete found->second;
    external_decoders_.erase(found);
    return 0;
  }

  webrtc::VideoEngine* const vie;
  webrtc::ViEBase* const base;
  webrtc::ViECodec* const codec;
  webrtc::ViENetwork* const network;
  webrtc::ViERTP_RTCP* const rtp;
  webrtc::ViERender* const render;
  webrtc::ViECapture* const capture;
  webrtc::ViEExternalCodec* const externalCodec;

 private:
  // Video engine no longer provides a socket implementation. There is,
  // however, a socket implementation in webrtc::test.
  typedef std::map<int, webrtc::test::VideoChannelTransport*>
  ChannelTransports;
  typedef std::map<int, VideoDecodeEncodeObserver*> Observers;
  typedef std::map<int, webrtc::MediaCodecVideoDecoder*> ExternalDecoders;

  void CreateTransport(int channel) {
    CHECK(GetTransport(channel) == NULL,
          "Transport already created for ViE channel, inconsistent state");
    channel_transports_[channel] =
        new webrtc::test::VideoChannelTransport(network, channel);
  }
  void DeleteTransport(int channel) {
    CHECK(GetTransport(channel) != NULL,
          "ViE channel missing transport, inconsistent state");
    delete channel_transports_[channel];
    channel_transports_.erase(channel);
  }

  ChannelTransports channel_transports_;
  Observers observers_;
  ExternalDecoders external_decoders_;
};

webrtc::VideoCodec* GetCodecInst(JNIEnv* jni, jobject j_codec) {
  jclass j_codec_class = jni->GetObjectClass(j_codec);
  jfieldID native_codec_id =
      jni->GetFieldID(j_codec_class, "nativeCodecInst", "J");
  jlong j_p = jni->GetLongField(j_codec, native_codec_id);
  return reinterpret_cast<webrtc::VideoCodec*>(j_p);
}

CameraDesc* GetCameraDesc(JNIEnv* jni, jobject j_camera) {
  jclass j_camera_class = jni->GetObjectClass(j_camera);
  jfieldID native_camera_id =
      jni->GetFieldID(j_camera_class, "nativeCameraDesc", "J");
  jlong j_p = jni->GetLongField(j_camera, native_camera_id);
  return reinterpret_cast<CameraDesc*>(j_p);
}

VideoEngineData* GetVideoEngineData(JNIEnv* jni, jobject j_vie) {
  jclass j_vie_class = jni->GetObjectClass(j_vie);
  jfieldID native_vie_id =
      jni->GetFieldID(j_vie_class, "nativeVideoEngine", "J");
  jlong j_p = jni->GetLongField(j_vie, native_vie_id);
  return reinterpret_cast<VideoEngineData*>(j_p);
}

}  // namespace

namespace webrtc_examples {

static const char* g_classes[] = {
  "org/webrtc/webrtcdemo/CameraDesc",
  "org/webrtc/webrtcdemo/RtcpStatistics",
  "org/webrtc/webrtcdemo/VideoCodecInst",
  "org/webrtc/webrtcdemo/VideoDecodeEncodeObserver",
  "org/webrtc/webrtcdemo/MediaCodecVideoDecoder"};

void SetVieDeviceObjects(JavaVM* vm) {
  CHECK(vm, "Trying to register NULL vm");
  CHECK(!g_vm, "Trying to re-register vm");
  g_vm = vm;
  webrtc::AttachThreadScoped ats(g_vm);
  JNIEnv* jni = ats.env();
  g_class_reference_holder = new ClassReferenceHolder(
      jni, g_classes, arraysize(g_classes));
}

void ClearVieDeviceObjects() {
  CHECK(g_vm, "Clearing vm without it being set");
  {
    webrtc::AttachThreadScoped ats(g_vm);
    g_class_reference_holder->FreeReferences(ats.env());
  }
  g_vm = NULL;
  delete g_class_reference_holder;
  g_class_reference_holder = NULL;
}

}  // namespace webrtc_examples

JOWW(jlong, VideoEngine_create)(JNIEnv* jni, jclass) {
  VideoEngineData* vie_data = new VideoEngineData();
  return jlongFromPointer(vie_data);
}

JOWW(jint, VideoEngine_init)(JNIEnv* jni, jobject j_vie) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->base->Init();
}

JOWW(jint, VideoEngine_setVoiceEngine)(JNIEnv* jni, jobject j_vie,
                                       jobject j_voe) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  webrtc::VoiceEngine* voe = GetVoiceEngine(jni, j_voe);
  return vie_data->base->SetVoiceEngine(voe);
}

JOWW(void, VideoEngine_dispose)(JNIEnv* jni, jobject j_vie) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  delete vie_data;
}

JOWW(jint, VideoEngine_startSend)(JNIEnv* jni, jobject j_vie, jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->base->StartSend(channel);
}

JOWW(jint, VideoEngine_stopRender)(JNIEnv* jni, jobject j_vie, jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->render->StopRender(channel);
}

JOWW(jint, VideoEngine_stopSend)(JNIEnv* jni, jobject j_vie, jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->base->StopSend(channel);
}

JOWW(jint, VideoEngine_startReceive)(JNIEnv* jni, jobject j_vie, jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->base->StartReceive(channel);
}

JOWW(jint, VideoEngine_stopReceive)(JNIEnv* jni, jobject j_vie, jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->base->StopReceive(channel);
}

JOWW(jint, VideoEngine_createChannel)(JNIEnv* jni, jobject j_vie) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->CreateChannel();
}

JOWW(jint, VideoEngine_deleteChannel)(JNIEnv* jni, jobject j_vie,
                                      jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->DeleteChannel(channel);
}

JOWW(jint,
     VideoEngine_connectAudioChannel(JNIEnv* jni, jobject j_vie,
                                     jint video_channel, jint audio_channel)) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->base->ConnectAudioChannel(video_channel, audio_channel);
}

JOWW(jint, VideoEngine_setLocalReceiver)(JNIEnv* jni, jobject j_vie,
                                         jint channel, jint port) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->GetTransport(channel)->SetLocalReceiver(port);
}

JOWW(jint, VideoEngine_setSendDestination)(JNIEnv* jni, jobject j_vie,
                                           jint channel, jint port,
                                           jstring j_addr) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  std::string addr = JavaToStdString(jni, j_addr);
  webrtc::test::VideoChannelTransport* transport =
      vie_data->GetTransport(channel);
  return transport->SetSendDestination(addr.c_str(), port);
}

JOWW(jint, VideoEngine_setReceiveCodec)(JNIEnv* jni, jobject j_vie,
                                        jint channel, jobject j_codec) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  webrtc::VideoCodec* codec = GetCodecInst(jni, j_codec);
  return vie_data->codec->SetReceiveCodec(channel, *codec);
}

JOWW(jint, VideoEngine_setSendCodec)(JNIEnv* jni, jobject j_vie, jint channel,
                                     jobject j_codec) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  webrtc::VideoCodec* codec = GetCodecInst(jni, j_codec);
  return vie_data->codec->SetSendCodec(channel, *codec);
}

JOWW(jint, VideoEngine_numberOfCodecs)(JNIEnv* jni, jobject j_vie) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->codec->NumberOfCodecs();
}

JOWW(jobject, VideoEngine_getCodec)(JNIEnv* jni, jobject j_vie, jint index) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  webrtc::VideoCodec* codec = new webrtc::VideoCodec();
  CHECK(vie_data->codec->GetCodec(index, *codec) == 0,
        "getCodec must be called with valid index");
  jclass j_codec_class = GetClass("org/webrtc/webrtcdemo/VideoCodecInst");
  jmethodID j_codec_ctor = GetMethodID(jni, j_codec_class, "<init>", "(J)V");
  jobject j_codec =
      jni->NewObject(j_codec_class, j_codec_ctor, jlongFromPointer(codec));
  CHECK_JNI_EXCEPTION(jni, "error during NewObject");
  return j_codec;
}

JOWW(jint, VideoEngine_addRenderer)(JNIEnv* jni, jobject j_vie, jint channel,
                                    jobject gl_surface, jint z_order,
                                    jfloat left, jfloat top, jfloat right,
                                    jfloat bottom) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->render->AddRenderer(channel, gl_surface, z_order, left, top,
                                       right, bottom);
}

JOWW(jint, VideoEngine_removeRenderer)(JNIEnv* jni, jobject j_vie,
                                       jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->render->RemoveRenderer(channel);
}

JOWW(jint, VideoEngine_registerExternalReceiveCodec)(JNIEnv* jni, jobject j_vie,
                                                     jint channel, jint pl_type,
                                                     jobject decoder,
                                                     bool internal_source) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->RegisterExternalReceiveCodec(channel, pl_type, decoder,
                                                true);
}

JOWW(jint,
     VideoEngine_deRegisterExternalReceiveCodec)(JNIEnv* jni, jobject j_vie,
                                                 jint channel, jint pl_type) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->DeRegisterExternalReceiveCodec(channel, pl_type);
}

JOWW(jint, VideoEngine_startRender)(JNIEnv* jni, jobject j_vie, jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->render->StartRender(channel);
}

JOWW(jint, VideoEngine_numberOfCaptureDevices)(JNIEnv* jni, jobject j_vie) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->capture->NumberOfCaptureDevices();
}

JOWW(jobject,
     VideoEngine_getCaptureDevice(JNIEnv* jni, jobject j_vie, jint index)) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  CameraDesc* camera_info = new CameraDesc();
  if (vie_data->capture->GetCaptureDevice(
          index, camera_info->name, sizeof(camera_info->name),
          camera_info->unique_id, sizeof(camera_info->unique_id)) != 0) {
    delete camera_info;
    return NULL;
  }
  jclass j_camera_class = GetClass("org/webrtc/webrtcdemo/CameraDesc");
  jmethodID j_camera_ctor = GetMethodID(jni, j_camera_class, "<init>", "(J)V");
  jobject j_camera = jni->NewObject(j_camera_class, j_camera_ctor,
                                    jlongFromPointer(camera_info));
  CHECK_JNI_EXCEPTION(jni, "error during NewObject");
  return j_camera;
}

JOWW(jint, VideoEngine_allocateCaptureDevice)(JNIEnv* jni, jobject j_vie,
                                              jobject j_camera) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  CameraDesc* camera_info = GetCameraDesc(jni, j_camera);
  jint capture_id;
  if (vie_data->capture->AllocateCaptureDevice(camera_info->unique_id,
                                               sizeof(camera_info->unique_id),
                                               capture_id) != 0) {
    return -1;
  }
  return capture_id;
}

JOWW(jint, VideoEngine_connectCaptureDevice)(JNIEnv* jni, jobject j_vie,
                                             jint camera_num, jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->capture->ConnectCaptureDevice(camera_num, channel);
}

JOWW(jint, VideoEngine_startCapture)(JNIEnv* jni, jobject j_vie,
                                     jint camera_num) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->capture->StartCapture(camera_num);
}

JOWW(jint, VideoEngine_stopCapture)(JNIEnv* jni, jobject j_vie,
                                    jint camera_id) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->capture->StopCapture(camera_id);
}

JOWW(jint, VideoEngine_releaseCaptureDevice)(JNIEnv* jni, jobject j_vie,
                                             jint camera_id) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->capture->ReleaseCaptureDevice(camera_id);
}

JOWW(jint, VideoEngine_getOrientation)(JNIEnv* jni, jobject j_vie,
                                       jobject j_camera) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  CameraDesc* camera_info = GetCameraDesc(jni, j_camera);
  webrtc::VideoRotation orientation;
  if (vie_data->capture->GetOrientation(camera_info->unique_id, orientation) !=
      0) {
    return -1;
  }
  return static_cast<jint>(orientation);
}

JOWW(jint, VideoEngine_setVideoRotations)(JNIEnv* jni,
                                          jobject j_vie,
                                          jint capture_id,
                                          jint degrees) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->capture->SetVideoRotation(
      capture_id, static_cast<webrtc::VideoRotation>(degrees));
}

JOWW(jint, VideoEngine_setNackStatus)(JNIEnv* jni, jobject j_vie, jint channel,
                                      jboolean enable) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->rtp->SetNACKStatus(channel, enable);
}

JOWW(jint, VideoEngine_setKeyFrameRequestMethod)(JNIEnv* jni, jobject j_vie,
                                                 jint channel,
                                                 jint request_method) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->rtp->SetKeyFrameRequestMethod(
      channel, static_cast<webrtc::ViEKeyFrameRequestMethod>(request_method));
}

JOWW(jobject, VideoEngine_getReceivedRtcpStatistics)(JNIEnv* jni, jobject j_vie,
                                                     jint channel) {
  unsigned short fraction_lost;  // NOLINT
  unsigned int cumulative_lost;  // NOLINT
  unsigned int extended_max;     // NOLINT
  unsigned int jitter;           // NOLINT
  int64_t rtt_ms;
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  if (vie_data->rtp->GetReceivedRTCPStatistics(channel, fraction_lost,
                                               cumulative_lost, extended_max,
                                               jitter, rtt_ms) != 0) {
    return NULL;
  }
  jclass j_rtcp_statistics_class =
      GetClass("org/webrtc/webrtcdemo/RtcpStatistics");
  jmethodID j_rtcp_statistics_ctor =
      GetMethodID(jni, j_rtcp_statistics_class, "<init>", "(IIIII)V");
  jobject j_rtcp_statistics =
      jni->NewObject(j_rtcp_statistics_class, j_rtcp_statistics_ctor,
                     fraction_lost, cumulative_lost, extended_max, jitter,
                     static_cast<int>(rtt_ms));
  CHECK_JNI_EXCEPTION(jni, "error during NewObject");
  return j_rtcp_statistics;
}

JOWW(jint, VideoEngine_registerObserver)(JNIEnv* jni, jobject j_vie,
                                         jint channel, jobject callback) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->RegisterObserver(channel, callback);
}

JOWW(jint, VideoEngine_deregisterObserver)(JNIEnv* jni, jobject j_vie,
                                           jint channel) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->DeregisterObserver(channel);
}

JOWW(jint, VideoEngine_setTraceFile)(JNIEnv* jni, jobject, jstring j_filename,
                                     jboolean file_counter) {
  std::string filename = JavaToStdString(jni, j_filename);
  return webrtc::VideoEngine::SetTraceFile(filename.c_str(), file_counter);
}

JOWW(jint, VideoEngine_nativeSetTraceFilter)(JNIEnv* jni, jobject,
                                             jint filter) {
  return webrtc::VideoEngine::SetTraceFilter(filter);
}

JOWW(jint, VideoEngine_startRtpDump)(JNIEnv* jni, jobject j_vie, jint channel,
                                     jstring j_filename, jint direction) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  std::string filename = JavaToStdString(jni, j_filename);
  return vie_data->rtp->StartRTPDump(
      channel, filename.c_str(), static_cast<webrtc::RTPDirections>(direction));
}

JOWW(jint, VideoEngine_stopRtpDump)(JNIEnv* jni, jobject j_vie, jint channel,
                                    jint direction) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->rtp->StopRTPDump(
      channel, static_cast<webrtc::RTPDirections>(direction));
}

JOWW(void, VideoCodecInst_dispose)(JNIEnv* jni, jobject j_codec) {
  delete GetCodecInst(jni, j_codec);
}

JOWW(jint, VideoCodecInst_plType)(JNIEnv* jni, jobject j_codec) {
  return GetCodecInst(jni, j_codec)->plType;
}

JOWW(jstring, VideoCodecInst_name)(JNIEnv* jni, jobject j_codec) {
  return jni->NewStringUTF(GetCodecInst(jni, j_codec)->plName);
}

JOWW(jint, VideoCodecInst_width)(JNIEnv* jni, jobject j_codec) {
  return GetCodecInst(jni, j_codec)->width;
}

JOWW(void, VideoCodecInst_setWidth)(JNIEnv* jni, jobject j_codec, jint width) {
  GetCodecInst(jni, j_codec)->width = width;
}

JOWW(jint, VideoCodecInst_height)(JNIEnv* jni, jobject j_codec) {
  return GetCodecInst(jni, j_codec)->height;
}

JOWW(void, VideoCodecInst_setHeight)(JNIEnv* jni, jobject j_codec,
                                     jint height) {
  GetCodecInst(jni, j_codec)->height = height;
}

JOWW(jint, VideoCodecInst_startBitRate)(JNIEnv* jni, jobject j_codec) {
  return GetCodecInst(jni, j_codec)->startBitrate;
}

JOWW(void, VideoCodecInst_setStartBitRate)(JNIEnv* jni, jobject j_codec,
                                           jint bitrate) {
  GetCodecInst(jni, j_codec)->startBitrate = bitrate;
}

JOWW(jint, VideoCodecInst_maxBitRate)(JNIEnv* jni, jobject j_codec) {
  return GetCodecInst(jni, j_codec)->maxBitrate;
}

JOWW(void, VideoCodecInst_setMaxBitRate)(JNIEnv* jni, jobject j_codec,
                                         jint bitrate) {
  GetCodecInst(jni, j_codec)->maxBitrate = bitrate;
}

JOWW(jint, VideoCodecInst_maxFrameRate)(JNIEnv* jni, jobject j_codec) {
  return GetCodecInst(jni, j_codec)->maxFramerate;
}

JOWW(void, VideoCodecInst_setMaxFrameRate)(JNIEnv* jni, jobject j_codec,
                                           jint framerate) {
  GetCodecInst(jni, j_codec)->maxFramerate = framerate;
}

JOWW(void, CameraDesc_dispose)(JNIEnv* jni, jobject j_camera) {
  delete GetCameraDesc(jni, j_camera);
}

JOWW(jint, VideoEngine_setLocalSSRC)(JNIEnv* jni, jobject j_vie, jint channel,
                                      jint ssrc) {
  VideoEngineData* vie_data = GetVideoEngineData(jni, j_vie);
  return vie_data->rtp->SetLocalSSRC(channel, ssrc);
}
