/*
 *  Copyright (c) 2011 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 "video_engine/vie_capturer.h"

#include "modules/interface/module_common_types.h"
#include "modules/utility/interface/process_thread.h"
#include "modules/video_capture/main/interface/video_capture_factory.h"
#include "modules/video_processing/main/interface/video_processing.h"
#include "modules/video_render/main/interface/video_render_defines.h"
#include "system_wrappers/interface/critical_section_wrapper.h"
#include "system_wrappers/interface/event_wrapper.h"
#include "system_wrappers/interface/thread_wrapper.h"
#include "system_wrappers/interface/trace.h"
#include "video_engine/include/vie_image_process.h"
#include "video_engine/vie_defines.h"
#include "video_engine/vie_encoder.h"

namespace webrtc {

const int kThreadWaitTimeMs = 100;
const int kMaxDeliverWaitTime = 500;

ViECapturer::ViECapturer(int capture_id,
                         int engine_id,
                         ProcessThread& module_process_thread)
    : ViEFrameProviderBase(capture_id, engine_id),
      capture_cs_(CriticalSectionWrapper::CreateCriticalSection()),
      deliver_cs_(CriticalSectionWrapper::CreateCriticalSection()),
      capture_module_(NULL),
      external_capture_module_(NULL),
      module_process_thread_(module_process_thread),
      capture_id_(capture_id),
      capture_thread_(*ThreadWrapper::CreateThread(ViECaptureThreadFunction,
                                                   this, kHighPriority,
                                                   "ViECaptureThread")),
      capture_event_(*EventWrapper::Create()),
      deliver_event_(*EventWrapper::Create()),
      effect_filter_(NULL),
      image_proc_module_(NULL),
      image_proc_module_ref_counter_(0),
      deflicker_frame_stats_(NULL),
      brightness_frame_stats_(NULL),
      current_brightness_level_(Normal),
      reported_brightness_level_(Normal),
      denoising_enabled_(false),
      observer_cs_(CriticalSectionWrapper::CreateCriticalSection()),
      observer_(NULL),
      encoding_cs_(CriticalSectionWrapper::CreateCriticalSection()),
      capture_encoder_(NULL),
      encode_complete_callback_(NULL),
      vie_encoder_(NULL),
      vcm_(NULL),
      decoder_initialized_(false) {
  WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id, capture_id),
               "ViECapturer::ViECapturer(capture_id: %d, engine_id: %d)",
               capture_id, engine_id);
  unsigned int t_id = 0;
  if (capture_thread_.Start(t_id)) {
    WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id, capture_id),
                 "%s: thread started: %u", __FUNCTION__, t_id);
  } else {
    assert(false);
  }
}

ViECapturer::~ViECapturer() {
  WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id_, capture_id_),
               "ViECapturer::~ViECapturer() - capture_id: %d, engine_id: %d",
               capture_id_, engine_id_);

  // Stop the thread.
  deliver_cs_->Enter();
  capture_cs_->Enter();
  capture_thread_.SetNotAlive();
  capture_event_.Set();
  capture_cs_->Leave();
  deliver_cs_->Leave();

  provider_cs_->Enter();
  if (vie_encoder_) {
    vie_encoder_->DeRegisterExternalEncoder(codec_.plType);
  }
  provider_cs_->Leave();

  // Stop the camera input.
  if (capture_module_) {
    module_process_thread_.DeRegisterModule(capture_module_);
    capture_module_->DeRegisterCaptureDataCallback();
    capture_module_->Release();
    capture_module_ = NULL;
  }
  if (capture_thread_.Stop()) {
    // Thread stopped.
    delete &capture_thread_;
    delete &capture_event_;
    delete &deliver_event_;
  } else {
    assert(false);
    WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer,
                 ViEId(engine_id_, capture_id_),
                 "%s: Not able to stop capture thread for device %d, leaking",
                 __FUNCTION__, capture_id_);
  }

  if (image_proc_module_) {
    VideoProcessingModule::Destroy(image_proc_module_);
  }
  if (deflicker_frame_stats_) {
    delete deflicker_frame_stats_;
    deflicker_frame_stats_ = NULL;
  }
  delete brightness_frame_stats_;
  if (vcm_) {
    delete vcm_;
  }
}

ViECapturer* ViECapturer::CreateViECapture(
    int capture_id,
    int engine_id,
    VideoCaptureModule& capture_module,
    ProcessThread& module_process_thread) {
  ViECapturer* capture = new ViECapturer(capture_id, engine_id,
                                         module_process_thread);
  if (!capture || capture->Init(capture_module) != 0) {
    delete capture;
    capture = NULL;
  }
  return capture;
}

WebRtc_Word32 ViECapturer::Init(VideoCaptureModule& capture_module) {
  assert(capture_module_ == NULL);
  capture_module_ = &capture_module;
  capture_module_->RegisterCaptureDataCallback(*this);
  capture_module_->AddRef();
  if (module_process_thread_.RegisterModule(capture_module_) != 0) {
    return -1;
  }

  return 0;
}

ViECapturer* ViECapturer::CreateViECapture(
    int capture_id,
    int engine_id,
    const WebRtc_UWord8* device_unique_idUTF8,
    const WebRtc_UWord32 device_unique_idUTF8Length,
    ProcessThread& module_process_thread) {
  ViECapturer* capture = new ViECapturer(capture_id, engine_id,
                                         module_process_thread);
  if (!capture ||
      capture->Init(device_unique_idUTF8, device_unique_idUTF8Length) != 0) {
    delete capture;
    capture = NULL;
  }
  return capture;
}

WebRtc_Word32 ViECapturer::Init(
    const WebRtc_UWord8* device_unique_idUTF8,
    const WebRtc_UWord32 device_unique_idUTF8Length) {
  assert(capture_module_ == NULL);
  if (device_unique_idUTF8 == NULL) {
    capture_module_  = VideoCaptureFactory::Create(
        ViEModuleId(engine_id_, capture_id_), external_capture_module_);
  } else {
    capture_module_ = VideoCaptureFactory::Create(
        ViEModuleId(engine_id_, capture_id_), device_unique_idUTF8);
  }
  if (!capture_module_) {
    return -1;
  }
  capture_module_->AddRef();
  capture_module_->RegisterCaptureDataCallback(*this);
  if (module_process_thread_.RegisterModule(capture_module_) != 0) {
    return -1;
  }

  return 0;
}

int ViECapturer::FrameCallbackChanged() {
  if (Started() && !EncoderActive() && !CaptureCapabilityFixed()) {
    // Reconfigure the camera if a new size is required and the capture device
    // does not provide encoded frames.
    int best_width;
    int best_height;
    int best_frame_rate;
    VideoCaptureCapability capture_settings;
    capture_module_->CaptureSettings(capture_settings);
    GetBestFormat(best_width, best_height, best_frame_rate);
    if (best_width != 0 && best_height != 0 && best_frame_rate != 0) {
      if (best_width != capture_settings.width ||
          best_height != capture_settings.height ||
          best_frame_rate != capture_settings.maxFPS ||
          capture_settings.codecType != kVideoCodecUnknown) {
        Stop();
        Start(requested_capability_);
      }
    }
  }
  return 0;
}

WebRtc_Word32 ViECapturer::Start(const CaptureCapability& capture_capability) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_), "%s",
               __FUNCTION__);
  int width;
  int height;
  int frame_rate;
  VideoCaptureCapability capability;
  requested_capability_ = capture_capability;
  if (EncoderActive()) {
    CriticalSectionScoped cs(encoding_cs_.get());
    capability.width = codec_.width;
    capability.height = codec_.height;
    capability.maxFPS = codec_.maxFramerate;
    capability.codecType = codec_.codecType;
    capability.rawType = kVideoI420;

  } else if (!CaptureCapabilityFixed()) {
    // Ask the observers for best size.
    GetBestFormat(width, height, frame_rate);
    if (width == 0) {
      width = kViECaptureDefaultWidth;
    }
    if (height == 0) {
      height = kViECaptureDefaultHeight;
    }
    if (frame_rate == 0) {
      frame_rate = kViECaptureDefaultFramerate;
    }
    capability.height = height;
    capability.width = width;
    capability.maxFPS = frame_rate;
    capability.rawType = kVideoI420;
    capability.codecType = kVideoCodecUnknown;
  } else {
    // Width, height and type specified with call to Start, not set by
    // observers.
    capability.width = requested_capability_.width;
    capability.height = requested_capability_.height;
    capability.maxFPS = requested_capability_.maxFPS;
    capability.rawType = requested_capability_.rawType;
    capability.interlaced = requested_capability_.interlaced;
  }
  return capture_module_->StartCapture(capability);
}

WebRtc_Word32 ViECapturer::Stop() {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_), "%s",
               __FUNCTION__);
  requested_capability_ = CaptureCapability();
  return capture_module_->StopCapture();
}

bool ViECapturer::Started() {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_), "%s",
               __FUNCTION__);
  return capture_module_->CaptureStarted();
}

const WebRtc_UWord8* ViECapturer::CurrentDeviceName() const {
  return capture_module_->CurrentDeviceName();
}

WebRtc_Word32 ViECapturer::SetCaptureDelay(WebRtc_Word32 delay_ms) {
  return capture_module_->SetCaptureDelay(delay_ms);
}

WebRtc_Word32 ViECapturer::SetRotateCapturedFrames(
  const RotateCapturedFrame rotation) {
  VideoCaptureRotation converted_rotation = kCameraRotate0;
  switch (rotation) {
    case RotateCapturedFrame_0:
      converted_rotation = kCameraRotate0;
      break;
    case RotateCapturedFrame_90:
      converted_rotation = kCameraRotate90;
      break;
    case RotateCapturedFrame_180:
      converted_rotation = kCameraRotate180;
      break;
    case RotateCapturedFrame_270:
      converted_rotation = kCameraRotate270;
      break;
    default:
      break;
  }
  return capture_module_->SetCaptureRotation(converted_rotation);
}

int ViECapturer::IncomingFrame(unsigned char* video_frame,
                               unsigned int video_frame_length,
                               unsigned short width,
                               unsigned short height,
                               RawVideoType video_type,
                               unsigned long long capture_time) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "ExternalCapture::IncomingFrame width %d, height %d, "
               "capture_time %u", width, height, capture_time);

  if (!external_capture_module_) {
    return -1;
  }
  VideoCaptureCapability capability;
  capability.width = width;
  capability.height = height;
  capability.rawType = video_type;
  return external_capture_module_->IncomingFrame(video_frame,
                                                 video_frame_length,
                                                 capability, capture_time);
}

int ViECapturer::IncomingFrameI420(const ViEVideoFrameI420& video_frame,
                                   unsigned long long capture_time) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "ExternalCapture::IncomingFrame width %d, height %d, "
               " capture_time %u", video_frame.width, video_frame.height,
               capture_time);

  if (!external_capture_module_) {
    return -1;
  }

  VideoFrameI420 frame;
  frame.width = video_frame.width;
  frame.height = video_frame.height;
  frame.y_plane = video_frame.y_plane;
  frame.u_plane = video_frame.u_plane;
  frame.v_plane = video_frame.v_plane;
  frame.y_pitch = video_frame.y_pitch;
  frame.u_pitch = video_frame.u_pitch;
  frame.v_pitch = video_frame.v_pitch;

  return external_capture_module_->IncomingFrameI420(frame, capture_time);
}

void ViECapturer::OnIncomingCapturedFrame(const WebRtc_Word32 capture_id,
                                          VideoFrame& video_frame,
                                          VideoCodecType codec_type) {
  WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_id: %d)", __FUNCTION__, capture_id);

  CriticalSectionScoped cs(capture_cs_.get());
  if (codec_type != kVideoCodecUnknown) {
    if (encoded_frame_.Length() != 0) {
      // The last encoded frame has not been sent yet. Need to wait.
      deliver_event_.Reset();
      WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s(capture_id: %d) Last encoded frame not yet delivered.",
                   __FUNCTION__, capture_id);
      capture_cs_->Leave();
      // Wait for the coded frame to be sent before unblocking this.
      deliver_event_.Wait(kMaxDeliverWaitTime);
      assert(encoded_frame_.Length() == 0);
      capture_cs_->Enter();
    }
    encoded_frame_.SwapFrame(video_frame);
  } else {
    captured_frame_.SwapFrame(video_frame);
  }
  capture_event_.Set();
  return;
}

void ViECapturer::OnCaptureDelayChanged(const WebRtc_Word32 id,
                                        const WebRtc_Word32 delay) {
  WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_id: %d) delay %d", __FUNCTION__, capture_id_,
               delay);

  // Deliver the network delay to all registered callbacks.
  ViEFrameProviderBase::SetFrameDelay(delay);
  CriticalSectionScoped cs(encoding_cs_.get());
  if (vie_encoder_) {
    vie_encoder_->DelayChanged(id, delay);
  }
}

WebRtc_Word32 ViECapturer::RegisterEffectFilter(
    ViEEffectFilter* effect_filter) {
  CriticalSectionScoped cs(deliver_cs_.get());

  if (!effect_filter) {
    if (!effect_filter_) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: no effect filter added for capture device %d",
                   __FUNCTION__, capture_id_);
      return -1;
    }
    WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
                 "%s: deregister effect filter for device %d", __FUNCTION__,
                 capture_id_);
  } else {
    if (effect_filter_) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: effect filter already added for capture device %d",
                   __FUNCTION__, capture_id_);
      return -1;
    }
    WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
                 "%s: register effect filter for device %d", __FUNCTION__,
                 capture_id_);
  }
  effect_filter_ = effect_filter;
  return 0;
}

WebRtc_Word32 ViECapturer::IncImageProcRefCount() {
  if (!image_proc_module_) {
    assert(image_proc_module_ref_counter_ == 0);
    image_proc_module_ = VideoProcessingModule::Create(
        ViEModuleId(engine_id_, capture_id_));
    if (!image_proc_module_) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: could not create video processing module",
                   __FUNCTION__);
      return -1;
    }
  }
  image_proc_module_ref_counter_++;
  return 0;
}

WebRtc_Word32 ViECapturer::DecImageProcRefCount() {
  image_proc_module_ref_counter_--;
  if (image_proc_module_ref_counter_ == 0) {
    // Destroy module.
    VideoProcessingModule::Destroy(image_proc_module_);
    image_proc_module_ = NULL;
  }
  return 0;
}

WebRtc_Word32 ViECapturer::EnableDenoising(bool enable) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d, enable: %d)", __FUNCTION__,
               capture_id_, enable);

  CriticalSectionScoped cs(deliver_cs_.get());
  if (enable) {
    if (denoising_enabled_) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: denoising already enabled", __FUNCTION__);
      return -1;
    }
    denoising_enabled_ = true;
    if (IncImageProcRefCount() != 0) {
      return -1;
    }
  } else {
    if (denoising_enabled_ == false) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: denoising not enabled", __FUNCTION__);
      return -1;
    }
    denoising_enabled_ = false;
    DecImageProcRefCount();
  }

  return 0;
}

WebRtc_Word32 ViECapturer::EnableDeflickering(bool enable) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d, enable: %d)", __FUNCTION__,
               capture_id_, enable);

  CriticalSectionScoped cs(deliver_cs_.get());
  if (enable) {
    if (deflicker_frame_stats_) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: deflickering already enabled", __FUNCTION__);
      return -1;
    }
    if (IncImageProcRefCount() != 0) {
      return -1;
    }
    deflicker_frame_stats_ = new VideoProcessingModule::FrameStats();
  } else {
    if (deflicker_frame_stats_ == NULL) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: deflickering not enabled", __FUNCTION__);
      return -1;
    }
    DecImageProcRefCount();
    delete deflicker_frame_stats_;
    deflicker_frame_stats_ = NULL;
  }
  return 0;
}

WebRtc_Word32 ViECapturer::EnableBrightnessAlarm(bool enable) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d, enable: %d)", __FUNCTION__,
               capture_id_, enable);

  CriticalSectionScoped cs(deliver_cs_.get());
  if (enable) {
    if (brightness_frame_stats_) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: BrightnessAlarm already enabled", __FUNCTION__);
      return -1;
    }
    if (IncImageProcRefCount() != 0) {
      return -1;
    }
    brightness_frame_stats_ = new VideoProcessingModule::FrameStats();
  } else {
    DecImageProcRefCount();
    if (brightness_frame_stats_ == NULL) {
      WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: deflickering not enabled", __FUNCTION__);
      return -1;
    }
    delete brightness_frame_stats_;
    brightness_frame_stats_ = NULL;
  }
  return 0;
}

bool ViECapturer::ViECaptureThreadFunction(void* obj) {
  return static_cast<ViECapturer*>(obj)->ViECaptureProcess();
}

bool ViECapturer::ViECaptureProcess() {
  if (capture_event_.Wait(kThreadWaitTimeMs) == kEventSignaled) {
    deliver_cs_->Enter();
    if (captured_frame_.Length() > 0) {
      // New I420 frame.
      capture_cs_->Enter();
      deliver_frame_.SwapFrame(captured_frame_);
      captured_frame_.SetLength(0);
      capture_cs_->Leave();
      DeliverI420Frame(deliver_frame_);
    }
    if (encoded_frame_.Length() > 0) {
      capture_cs_->Enter();
      deliver_frame_.SwapFrame(encoded_frame_);
      encoded_frame_.SetLength(0);
      deliver_event_.Set();
      capture_cs_->Leave();
      DeliverCodedFrame(deliver_frame_);
    }
    deliver_cs_->Leave();
    if (current_brightness_level_ != reported_brightness_level_) {
      CriticalSectionScoped cs(observer_cs_.get());
      if (observer_) {
        observer_->BrightnessAlarm(id_, current_brightness_level_);
        reported_brightness_level_ = current_brightness_level_;
      }
    }
  }
  // We're done!
  return true;
}

void ViECapturer::DeliverI420Frame(VideoFrame& video_frame) {
  // Apply image enhancement and effect filter.
  if (deflicker_frame_stats_) {
    if (image_proc_module_->GetFrameStats(*deflicker_frame_stats_,
                                          video_frame) == 0) {
      image_proc_module_->Deflickering(video_frame, *deflicker_frame_stats_);
    } else {
      WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, capture_id_),
                   "%s: could not get frame stats for captured frame",
                   __FUNCTION__);
    }
  }
  if (denoising_enabled_) {
    image_proc_module_->Denoising(video_frame);
  }
  if (brightness_frame_stats_) {
    if (image_proc_module_->GetFrameStats(*brightness_frame_stats_,
                                          video_frame) == 0) {
      WebRtc_Word32 brightness = image_proc_module_->BrightnessDetection(
          video_frame, *brightness_frame_stats_);

      switch (brightness) {
      case VideoProcessingModule::kNoWarning:
        current_brightness_level_ = Normal;
        break;
      case VideoProcessingModule::kDarkWarning:
        current_brightness_level_ = Dark;
        break;
      case VideoProcessingModule::kBrightWarning:
        current_brightness_level_ = Bright;
        break;
      default:
        WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
                     "%s: Brightness detection failed", __FUNCTION__);
      }
    }
  }
  if (effect_filter_) {
    effect_filter_->Transform(video_frame.Length(), video_frame.Buffer(),
                              video_frame.TimeStamp(), video_frame.Width(),
                              video_frame.Height());
  }
  // Deliver the captured frame to all observers (channels, renderer or file).
  ViEFrameProviderBase::DeliverFrame(video_frame);
}

void ViECapturer::DeliverCodedFrame(VideoFrame& video_frame) {
  if (encode_complete_callback_) {
    EncodedImage encoded_image(video_frame.Buffer(), video_frame.Length(),
                               video_frame.Size());
    encoded_image._timeStamp = 90 * (WebRtc_UWord32) video_frame.RenderTimeMs();
    encode_complete_callback_->Encoded(encoded_image);
  }

  if (NumberOfRegisteredFrameCallbacks() > 0 && decoder_initialized_) {
    video_frame.Swap(decode_buffer_.payloadData, decode_buffer_.bufferSize,
                     decode_buffer_.payloadSize);
    decode_buffer_.encodedHeight = video_frame.Height();
    decode_buffer_.encodedWidth = video_frame.Width();
    decode_buffer_.renderTimeMs = video_frame.RenderTimeMs();
    decode_buffer_.timeStamp = 90 * (WebRtc_UWord32) video_frame.RenderTimeMs();
    decode_buffer_.payloadType = codec_.plType;
    vcm_->DecodeFromStorage(decode_buffer_);
  }
}

int ViECapturer::DeregisterFrameCallback(
    const ViEFrameCallback* callbackObject) {
  provider_cs_->Enter();
  if (callbackObject == vie_encoder_) {
    // Don't use this camera as encoder anymore. Need to tell the ViEEncoder.
    ViEEncoder* vie_encoder = NULL;
    vie_encoder = vie_encoder_;
    vie_encoder_ = NULL;
    provider_cs_->Leave();

    // Need to take this here in order to avoid deadlock with VCM. The reason is
    // that VCM will call ::Release and a deadlock can occur.
    deliver_cs_->Enter();
    vie_encoder->DeRegisterExternalEncoder(codec_.plType);
    deliver_cs_->Leave();
    return 0;
  }
  provider_cs_->Leave();
  return ViEFrameProviderBase::DeregisterFrameCallback(callbackObject);
}

bool ViECapturer::IsFrameCallbackRegistered(
    const ViEFrameCallback* callbackObject) {
  CriticalSectionScoped cs(provider_cs_.get());
  if (callbackObject == vie_encoder_) {
    return true;
  }
  return ViEFrameProviderBase::IsFrameCallbackRegistered(callbackObject);
}

WebRtc_Word32 ViECapturer::PreEncodeToViEEncoder(const VideoCodec& codec,
                                                 ViEEncoder& vie_encoder,
                                                 WebRtc_Word32 vie_encoder_id) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d)", __FUNCTION__, capture_id_);
  if (vie_encoder_ && &vie_encoder != vie_encoder_) {
    WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
                 "%s(capture_device_id: %d Capture device already encoding)",
                 __FUNCTION__, capture_id_);
    return -1;
  }

  CriticalSectionScoped cs(encoding_cs_.get());
  VideoCaptureModule::VideoCaptureEncodeInterface* capture_encoder =
    capture_module_->GetEncodeInterface(codec);
  if (!capture_encoder) {
    // Encoding not supported?
    return -1;
  }
  capture_encoder_ = capture_encoder;

  // Create VCM module used for decoding frames if needed.
  if (!vcm_) {
    vcm_ = VideoCodingModule::Create(capture_id_);
  }

  if (vie_encoder.RegisterExternalEncoder(this, codec.plType) != 0) {
    return -1;
  }
  if (vie_encoder.SetEncoder(codec) != 0) {
    vie_encoder.DeRegisterExternalEncoder(codec.plType);
    return -1;
  }

  // Make sure the encoder is not an I420 observer.
  ViEFrameProviderBase::DeregisterFrameCallback(&vie_encoder);
  // Store the vie_encoder using this capture device.
  vie_encoder_ = &vie_encoder;
  vie_encoder_id_ = vie_encoder_id;
  memcpy(&codec_, &codec, sizeof(VideoCodec));
  return 0;
}

bool ViECapturer::EncoderActive() {
  return vie_encoder_ != NULL;
}

bool ViECapturer::CaptureCapabilityFixed() {
  return requested_capability_.width != 0 &&
      requested_capability_.height != 0 &&
      requested_capability_.maxFPS != 0;
}

WebRtc_Word32 ViECapturer::Version(WebRtc_Word8* version,
                                   WebRtc_Word32 length) const {
  return 0;
}

WebRtc_Word32 ViECapturer::InitEncode(const VideoCodec* codec_settings,
                                      WebRtc_Word32 number_of_cores,
                                      WebRtc_UWord32 max_payload_size) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d)", __FUNCTION__, capture_id_);

  CriticalSectionScoped cs(encoding_cs_.get());
  if (!capture_encoder_ || !codec_settings) {
    return WEBRTC_VIDEO_CODEC_ERROR;
  }

  if (vcm_) {
    // Initialize VCM to be able to decode frames if needed.
    if (vcm_->InitializeReceiver() == 0) {
      if (vcm_->RegisterReceiveCallback(this) == 0) {
        if (vcm_->RegisterReceiveCodec(codec_settings, number_of_cores,
                                       false) == 0) {
          decoder_initialized_ = true;
          WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
                       "%s(capture_device_id: %d) VCM Decoder initialized",
                       __FUNCTION__, capture_id_);
        }
      }
    }
  }
  return capture_encoder_->ConfigureEncoder(*codec_settings, max_payload_size);
}

WebRtc_Word32 ViECapturer::Encode(const RawImage& input_image,
                                  const CodecSpecificInfo* codec_specific_info,
                                  const VideoFrameType* frame_types) {
  CriticalSectionScoped cs(encoding_cs_.get());
  if (!capture_encoder_) {
    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  }
  if (*frame_types == kKeyFrame) {
    return capture_encoder_->EncodeFrameType(kVideoFrameKey);
  }
  if (*frame_types == kSkipFrame) {
    return capture_encoder_->EncodeFrameType(kFrameEmpty);
  }
  return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
}

WebRtc_Word32 ViECapturer::RegisterEncodeCompleteCallback(
    EncodedImageCallback* callback) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d)", __FUNCTION__, capture_id_);

  CriticalSectionScoped cs(deliver_cs_.get());
  if (!capture_encoder_) {
    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  }
  encode_complete_callback_ = callback;
  return 0;
}

WebRtc_Word32 ViECapturer::Release() {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d)", __FUNCTION__, capture_id_);
  {
    CriticalSectionScoped cs(deliver_cs_.get());
    encode_complete_callback_ = NULL;
  }

  {
    CriticalSectionScoped cs(encoding_cs_.get());

    decoder_initialized_ = false;
    codec_.codecType = kVideoCodecUnknown;
    // Reset the camera to output I420.
    capture_encoder_->ConfigureEncoder(codec_, 0);

    if (vie_encoder_) {
      // Need to add the encoder as an observer of I420.
      ViEFrameProviderBase::RegisterFrameCallback(vie_encoder_id_,
                                                  vie_encoder_);
    }
    vie_encoder_ = NULL;
  }
  return 0;
}

// Should reset the capture device to the state it was in after the InitEncode
// function. Current implementation do nothing.
WebRtc_Word32 ViECapturer::Reset() {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d)", __FUNCTION__, capture_id_);
  return 0;
}

WebRtc_Word32 ViECapturer::SetChannelParameters(WebRtc_UWord32 packet_loss,
                                                int rtt) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d)", __FUNCTION__, capture_id_);

  CriticalSectionScoped cs(encoding_cs_.get());
  if (!capture_encoder_) {
    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  }
  return capture_encoder_->SetChannelParameters(packet_loss, rtt);
}

WebRtc_Word32 ViECapturer::SetRates(WebRtc_UWord32 new_bit_rate,
                                    WebRtc_UWord32 frame_rate) {
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, capture_id_),
               "%s(capture_device_id: %d)", __FUNCTION__, capture_id_);

  CriticalSectionScoped cs(encoding_cs_.get());
  if (!capture_encoder_) {
    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
  }
  return capture_encoder_->SetRates(new_bit_rate, frame_rate);
}

WebRtc_Word32 ViECapturer::FrameToRender(VideoFrame& video_frame) {
  deliver_cs_->Enter();
  DeliverI420Frame(video_frame);
  deliver_cs_->Leave();
  return 0;
}

WebRtc_Word32 ViECapturer::RegisterObserver(ViECaptureObserver& observer) {
  if (observer_) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                 "%s Observer already registered", __FUNCTION__, capture_id_);
    return -1;
  }
  if (capture_module_->RegisterCaptureCallback(*this) != 0) {
    return -1;
  }
  capture_module_->EnableFrameRateCallback(true);
  capture_module_->EnableNoPictureAlarm(true);
  observer_ = &observer;
  return 0;
}

WebRtc_Word32 ViECapturer::DeRegisterObserver() {
  CriticalSectionScoped cs(observer_cs_.get());
  if (!observer_) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, capture_id_),
                 "%s No observer registered", __FUNCTION__, capture_id_);
    return -1;
  }
  capture_module_->EnableFrameRateCallback(false);
  capture_module_->EnableNoPictureAlarm(false);
  capture_module_->DeRegisterCaptureCallback();
  observer_ = NULL;
  return 0;
}

bool ViECapturer::IsObserverRegistered() {
  CriticalSectionScoped cs(observer_cs_.get());
  return observer_ != NULL;
}

void ViECapturer::OnCaptureFrameRate(const WebRtc_Word32 id,
                                     const WebRtc_UWord32 frame_rate) {
  WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, capture_id_),
               "OnCaptureFrameRate %d", frame_rate);

  CriticalSectionScoped cs(observer_cs_.get());
  observer_->CapturedFrameRate(id_, (WebRtc_UWord8) frame_rate);
}

void ViECapturer::OnNoPictureAlarm(const WebRtc_Word32 id,
                                   const VideoCaptureAlarm alarm) {
  WEBRTC_TRACE(kTraceStream, kTraceVideo, ViEId(engine_id_, capture_id_),
               "OnNoPictureAlarm %d", alarm);

  CriticalSectionScoped cs(observer_cs_.get());
  CaptureAlarm vie_alarm = (alarm == Raised) ? AlarmRaised : AlarmCleared;
  observer_->NoPictureAlarm(id, vie_alarm);
}

WebRtc_Word32 ViECapturer::SetCaptureDeviceImage(
    const VideoFrame& capture_device_image) {
  return capture_module_->StartSendImage(capture_device_image, 10);
}

}  // namespace webrtc
