/*
 *  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_engine/test/auto_test/primitives/general_primitives.h"

#include "webrtc/modules/video_capture/include/video_capture_factory.h"
#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"
#include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h"
#include "webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h"

void FindCaptureDeviceOnSystem(webrtc::ViECapture* capture,
                               char* device_name,
                               unsigned int device_name_length,
                               int* device_id,
                               webrtc::VideoCaptureModule** device_video) {

  bool capture_device_set = false;
  webrtc::VideoCaptureModule::DeviceInfo *dev_info =
      webrtc::VideoCaptureFactory::CreateDeviceInfo(0);

  const unsigned int kMaxUniqueIdLength = 256;
  char unique_id[kMaxUniqueIdLength];
  memset(unique_id, 0, kMaxUniqueIdLength);

  for (unsigned int i = 0; i < dev_info->NumberOfDevices(); i++) {
    EXPECT_EQ(0, dev_info->GetDeviceName(i, device_name, device_name_length,
                                         unique_id, kMaxUniqueIdLength));

    *device_video = webrtc::VideoCaptureFactory::Create(4571, unique_id);
    EXPECT_TRUE(*device_video != NULL);

    if (*device_video) {
      (*device_video)->AddRef();

      int error = capture->AllocateCaptureDevice(**device_video, *device_id);
      if (error == 0) {
        ViETest::Log("Using capture device: %s, captureId: %d.",
                     device_name, *device_id);
        capture_device_set = true;
        break;
      } else {
        (*device_video)->Release();
        (*device_video) = NULL;
      }
    }
  }
  delete dev_info;
  EXPECT_TRUE(capture_device_set) << "Found no suitable camera on your system.";
}

void RenderInWindow(webrtc::ViERender* video_render_interface,
                    int frame_provider_id,
                    void* os_window,
                    float z_index) {
  EXPECT_EQ(0,
            video_render_interface->AddRenderer(frame_provider_id, os_window,
                                                z_index, 0.0, 0.0, 1.0, 1.0));
  EXPECT_EQ(0, video_render_interface->StartRender(frame_provider_id));
}

void StopRenderInWindow(webrtc::ViERender* video_render_interface,
                        int frame_provider_id) {
  EXPECT_EQ(0, video_render_interface->StopRender(frame_provider_id));
  EXPECT_EQ(0, video_render_interface->RemoveRenderer(frame_provider_id));
}

void RenderToFile(webrtc::ViERender* renderer_interface,
                  int frame_provider_id,
                  ViEToFileRenderer *to_file_renderer) {
  EXPECT_EQ(0, renderer_interface->AddRenderer(
      frame_provider_id, webrtc::kVideoI420, to_file_renderer));
  EXPECT_EQ(0, renderer_interface->StartRender(frame_provider_id));
}

void ConfigureRtpRtcp(webrtc::ViERTP_RTCP* rtcp_interface,
                      ProtectionMethod protection_method,
                      int video_channel) {
  EXPECT_EQ(0, rtcp_interface->SetRTCPStatus(video_channel,
                                             webrtc::kRtcpCompound_RFC4585));
  EXPECT_EQ(0, rtcp_interface->SetKeyFrameRequestMethod(
      video_channel, webrtc::kViEKeyFrameRequestPliRtcp));
  EXPECT_EQ(0, rtcp_interface->SetTMMBRStatus(video_channel, true));
  switch (protection_method) {
    case kNack:
      EXPECT_EQ(0, rtcp_interface->SetNACKStatus(video_channel, true));
      break;
    case kHybridNackFec:
      const int kRedPayloadType = 96;
      const int kUlpFecPayloadType = 97;
      EXPECT_EQ(0, rtcp_interface->SetHybridNACKFECStatus(video_channel,
                                                          true,
                                                          kRedPayloadType,
                                                          kUlpFecPayloadType));
      break;
  }
}

bool FindSpecificCodec(webrtc::VideoCodecType of_type,
                       webrtc::ViECodec* codec_interface,
                       webrtc::VideoCodec* result) {

  memset(result, 0, sizeof(webrtc::VideoCodec));

  for (int i = 0; i < codec_interface->NumberOfCodecs(); i++) {
    webrtc::VideoCodec codec;
    memset(&codec, 0, sizeof(webrtc::VideoCodec));
    if (codec_interface->GetCodec(i, codec) != 0) {
      return false;
    }
    if (codec.codecType == of_type) {
      // Done
      *result = codec;
      return true;
    }
  }
  // Didn't find it
  return false;
}

void SetSuitableResolution(webrtc::VideoCodec* video_codec,
                           int forced_codec_width,
                           int forced_codec_height) {
  if (forced_codec_width != kDoNotForceResolution &&
      forced_codec_height != kDoNotForceResolution) {
    video_codec->width = forced_codec_width;
    video_codec->height = forced_codec_height;
  } else if (video_codec->codecType == webrtc::kVideoCodecI420) {
    // I420 is very bandwidth heavy, so limit it here.
    video_codec->width = 176;
    video_codec->height = 144;
  } else {
    // Otherwise go with 640x480.
    video_codec->width = 640;
    video_codec->height = 480;
  }
}
