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

#include <assert.h>

#include "webrtc/common_types.h"
#include "webrtc/modules/video_capture/include/video_capture_factory.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
#include "webrtc/video_engine/include/vie_errors.h"
#include "webrtc/video_engine/vie_capturer.h"
#include "webrtc/video_engine/vie_defines.h"

namespace webrtc {

ViEInputManager::ViEInputManager(const int engine_id, const Config& config)
    : config_(config),
      engine_id_(engine_id),
      map_cs_(CriticalSectionWrapper::CreateCriticalSection()),
      device_info_cs_(CriticalSectionWrapper::CreateCriticalSection()),
      vie_frame_provider_map_(),
      capture_device_info_(NULL),
      module_process_thread_(NULL) {
  for (int idx = 0; idx < kViEMaxCaptureDevices; idx++) {
    free_capture_device_id_[idx] = true;
  }
}

ViEInputManager::~ViEInputManager() {
  for (FrameProviderMap::iterator it = vie_frame_provider_map_.begin();
       it != vie_frame_provider_map_.end();
       ++it) {
    delete it->second;
  }

  delete capture_device_info_;
}
void ViEInputManager::SetModuleProcessThread(
    ProcessThread* module_process_thread) {
  assert(!module_process_thread_);
  module_process_thread_ = module_process_thread;
}

int ViEInputManager::NumberOfCaptureDevices() {
  CriticalSectionScoped cs(device_info_cs_.get());
  if (capture_device_info_ == NULL)
    capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
        ViEModuleId(engine_id_));
  assert(capture_device_info_);
  return capture_device_info_->NumberOfDevices();
}

int ViEInputManager::GetDeviceName(uint32_t device_number,
                                   char* device_nameUTF8,
                                   uint32_t device_name_length,
                                   char* device_unique_idUTF8,
                                   uint32_t device_unique_idUTF8Length) {
  CriticalSectionScoped cs(device_info_cs_.get());
  if (capture_device_info_ == NULL)
    capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
        ViEModuleId(engine_id_));
  assert(capture_device_info_);
  return capture_device_info_->GetDeviceName(device_number, device_nameUTF8,
                                             device_name_length,
                                             device_unique_idUTF8,
                                             device_unique_idUTF8Length);
}

int ViEInputManager::NumberOfCaptureCapabilities(
  const char* device_unique_idUTF8) {
  CriticalSectionScoped cs(device_info_cs_.get());
  if (capture_device_info_ == NULL)
    capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
        ViEModuleId(engine_id_));
  assert(capture_device_info_);
  return capture_device_info_->NumberOfCapabilities(device_unique_idUTF8);
}

int ViEInputManager::GetCaptureCapability(
    const char* device_unique_idUTF8,
    const uint32_t device_capability_number,
    CaptureCapability& capability) {
  CriticalSectionScoped cs(device_info_cs_.get());
  if (capture_device_info_ == NULL)
    capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
        ViEModuleId(engine_id_));
  assert(capture_device_info_);
  VideoCaptureCapability module_capability;
  int result = capture_device_info_->GetCapability(device_unique_idUTF8,
                                                   device_capability_number,
                                                   module_capability);
  if (result != 0)
    return result;

  // Copy from module type to public type.
  capability.expectedCaptureDelay = module_capability.expectedCaptureDelay;
  capability.height = module_capability.height;
  capability.width = module_capability.width;
  capability.interlaced = module_capability.interlaced;
  capability.rawType = module_capability.rawType;
  capability.codecType = module_capability.codecType;
  capability.maxFPS = module_capability.maxFPS;
  return result;
}

int ViEInputManager::GetOrientation(const char* device_unique_idUTF8,
                                    RotateCapturedFrame& orientation) {
  CriticalSectionScoped cs(device_info_cs_.get());
  if (capture_device_info_ == NULL)
    capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
        ViEModuleId(engine_id_));
  assert(capture_device_info_);
  VideoCaptureRotation module_orientation;
  int result = capture_device_info_->GetOrientation(device_unique_idUTF8,
                                                    module_orientation);
  // Copy from module type to public type.
  switch (module_orientation) {
    case kCameraRotate0:
      orientation = RotateCapturedFrame_0;
      break;
    case kCameraRotate90:
      orientation = RotateCapturedFrame_90;
      break;
    case kCameraRotate180:
      orientation = RotateCapturedFrame_180;
      break;
    case kCameraRotate270:
      orientation = RotateCapturedFrame_270;
      break;
  }
  return result;
}

int ViEInputManager::DisplayCaptureSettingsDialogBox(
    const char* device_unique_idUTF8,
    const char* dialog_titleUTF8,
    void* parent_window,
    uint32_t positionX,
    uint32_t positionY) {
  CriticalSectionScoped cs(device_info_cs_.get());
  if (capture_device_info_ == NULL)
    capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
        ViEModuleId(engine_id_));
  assert(capture_device_info_);
  return capture_device_info_->DisplayCaptureSettingsDialogBox(
           device_unique_idUTF8, dialog_titleUTF8, parent_window, positionX,
           positionY);
}

int ViEInputManager::CreateCaptureDevice(
    const char* device_unique_idUTF8,
    const uint32_t device_unique_idUTF8Length,
    int& capture_id) {
  CriticalSectionScoped cs(map_cs_.get());

  // Make sure the device is not already allocated.
  for (FrameProviderMap::iterator it = vie_frame_provider_map_.begin();
       it != vie_frame_provider_map_.end();
       ++it) {
    // Make sure this is a capture device.
    if (it->first >= kViECaptureIdBase && it->first <= kViECaptureIdMax) {
      ViECapturer* vie_capture = static_cast<ViECapturer*>(it->second);
      assert(vie_capture);
      // TODO(mflodman) Can we change input to avoid this cast?
      const char* device_name =
          reinterpret_cast<const char*>(vie_capture->CurrentDeviceName());
      if (strncmp(device_name, device_unique_idUTF8,
                  strlen(device_name)) == 0) {
        return kViECaptureDeviceAlreadyAllocated;
      }
    }
  }

  // Make sure the device name is valid.
  bool found_device = false;
  CriticalSectionScoped cs_devinfo(device_info_cs_.get());
  if (capture_device_info_ == NULL)
    capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(
        ViEModuleId(engine_id_));
  assert(capture_device_info_);
  for (uint32_t device_index = 0;
       device_index < capture_device_info_->NumberOfDevices(); ++device_index) {
    if (device_unique_idUTF8Length > kVideoCaptureUniqueNameLength) {
      // User's string length is longer than the max.
      return -1;
    }

    char found_name[kVideoCaptureDeviceNameLength] = "";
    char found_unique_name[kVideoCaptureUniqueNameLength] = "";
    capture_device_info_->GetDeviceName(device_index, found_name,
                                        kVideoCaptureDeviceNameLength,
                                        found_unique_name,
                                        kVideoCaptureUniqueNameLength);

    // TODO(mflodman) Can we change input to avoid this cast?
    const char* cast_id = reinterpret_cast<const char*>(device_unique_idUTF8);
    if (strncmp(cast_id, reinterpret_cast<const char*>(found_unique_name),
                strlen(cast_id)) == 0) {
      found_device = true;
      break;
    }
  }
  if (!found_device) {
    LOG(LS_ERROR) << "Capture device not found: " << device_unique_idUTF8;
    return kViECaptureDeviceDoesNotExist;
  }

  int newcapture_id = 0;
  if (!GetFreeCaptureId(&newcapture_id)) {
    LOG(LS_ERROR) << "All capture devices already allocated.";
    return kViECaptureDeviceMaxNoDevicesAllocated;
  }
  ViECapturer* vie_capture = ViECapturer::CreateViECapture(
      newcapture_id, engine_id_, config_, device_unique_idUTF8,
      device_unique_idUTF8Length, *module_process_thread_);
  if (!vie_capture) {
    ReturnCaptureId(newcapture_id);
    return kViECaptureDeviceUnknownError;
  }

  vie_frame_provider_map_[newcapture_id] = vie_capture;
  capture_id = newcapture_id;
  return 0;
}

int ViEInputManager::CreateCaptureDevice(VideoCaptureModule* capture_module,
                                         int& capture_id) {
  CriticalSectionScoped cs(map_cs_.get());
  int newcapture_id = 0;
  if (!GetFreeCaptureId(&newcapture_id)) {
    LOG(LS_ERROR) << "All capture devices already allocated.";
    return kViECaptureDeviceMaxNoDevicesAllocated;
  }

  ViECapturer* vie_capture = ViECapturer::CreateViECapture(
      newcapture_id, engine_id_, config_,
      capture_module, *module_process_thread_);
  if (!vie_capture) {
    ReturnCaptureId(newcapture_id);
    return kViECaptureDeviceUnknownError;
  }
  vie_frame_provider_map_[newcapture_id] = vie_capture;
  capture_id = newcapture_id;
  return 0;
}

int ViEInputManager::DestroyCaptureDevice(const int capture_id) {
  ViECapturer* vie_capture = NULL;
  {
    // We need exclusive access to the object to delete it.
    // Take this write lock first since the read lock is taken before map_cs_.
    ViEManagerWriteScoped wl(this);
    CriticalSectionScoped cs(map_cs_.get());

    vie_capture = ViECapturePtr(capture_id);
    if (!vie_capture) {
      LOG(LS_ERROR) << "No such capture device id: " << capture_id;
      return -1;
    }
    uint32_t num_callbacks =
        vie_capture->NumberOfRegisteredFrameCallbacks();
    if (num_callbacks > 0) {
      LOG(LS_WARNING) << num_callbacks << " still registered to capture id "
                      << capture_id << " when destroying capture device.";
    }
    vie_frame_provider_map_.erase(capture_id);
    ReturnCaptureId(capture_id);
    // Leave cs before deleting the capture object. This is because deleting the
    // object might cause deletions of renderers so we prefer to not have a lock
    // at that time.
  }
  delete vie_capture;
  return 0;
}

int ViEInputManager::CreateExternalCaptureDevice(
    ViEExternalCapture*& external_capture,
    int& capture_id) {
  CriticalSectionScoped cs(map_cs_.get());

  int newcapture_id = 0;
  if (GetFreeCaptureId(&newcapture_id) == false) {
    LOG(LS_ERROR) << "All capture devices already allocated.";
    return kViECaptureDeviceMaxNoDevicesAllocated;
  }

  ViECapturer* vie_capture = ViECapturer::CreateViECapture(
      newcapture_id, engine_id_, config_, NULL, 0, *module_process_thread_);
  if (!vie_capture) {
    ReturnCaptureId(newcapture_id);
    return kViECaptureDeviceUnknownError;
  }

  vie_frame_provider_map_[newcapture_id] = vie_capture;
  capture_id = newcapture_id;
  external_capture = vie_capture;
  return 0;
}

bool ViEInputManager::GetFreeCaptureId(int* freecapture_id) {
  for (int id = 0; id < kViEMaxCaptureDevices; id++) {
    if (free_capture_device_id_[id]) {
      // We found a free capture device id.
      free_capture_device_id_[id] = false;
      *freecapture_id = id + kViECaptureIdBase;
      return true;
    }
  }
  return false;
}

void ViEInputManager::ReturnCaptureId(int capture_id) {
  CriticalSectionScoped cs(map_cs_.get());
  if (capture_id >= kViECaptureIdBase &&
      capture_id < kViEMaxCaptureDevices + kViECaptureIdBase) {
    free_capture_device_id_[capture_id - kViECaptureIdBase] = true;
  }
  return;
}

ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(
    const ViEFrameCallback* capture_observer) const {
  assert(capture_observer);
  CriticalSectionScoped cs(map_cs_.get());

  for (FrameProviderMap::const_iterator it = vie_frame_provider_map_.begin();
       it != vie_frame_provider_map_.end();
       ++it) {
    if (it->second->IsFrameCallbackRegistered(capture_observer))
      return it->second;
  }

  // No capture device set for this channel.
  return NULL;
}

ViEFrameProviderBase* ViEInputManager::ViEFrameProvider(int provider_id) const {
  CriticalSectionScoped cs(map_cs_.get());

  FrameProviderMap::const_iterator it =
      vie_frame_provider_map_.find(provider_id);
  if (it == vie_frame_provider_map_.end())
    return NULL;
  return it->second;
}

ViECapturer* ViEInputManager::ViECapturePtr(int capture_id) const {
  if (!(capture_id >= kViECaptureIdBase &&
        capture_id <= kViECaptureIdBase + kViEMaxCaptureDevices)) {
    LOG(LS_ERROR) << "Capture device doesn't exist " << capture_id << ".";
    return NULL;
  }

  return static_cast<ViECapturer*>(ViEFrameProvider(capture_id));
}

ViEInputManagerScoped::ViEInputManagerScoped(
    const ViEInputManager& vie_input_manager)
    : ViEManagerScopedBase(vie_input_manager) {
}

ViECapturer* ViEInputManagerScoped::Capture(int capture_id) const {
  return static_cast<const ViEInputManager*>(vie_manager_)->ViECapturePtr(
      capture_id);
}

ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
    const ViEFrameCallback* capture_observer) const {
  return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
      capture_observer);
}

ViEFrameProviderBase* ViEInputManagerScoped::FrameProvider(
    int provider_id) const {
  return static_cast<const ViEInputManager*>(vie_manager_)->ViEFrameProvider(
      provider_id);
}

}  // namespace webrtc
