/*
 * libjingle
 * Copyright 2012 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/media/base/capturerenderadapter.h"

#include "talk/media/base/videocapturer.h"
#include "talk/media/base/videorenderer.h"
#include "webrtc/base/logging.h"

namespace cricket {

CaptureRenderAdapter::CaptureRenderAdapter(VideoCapturer* video_capturer)
    : video_capturer_(video_capturer) {
}

CaptureRenderAdapter::~CaptureRenderAdapter() {
  // Since the signal we're connecting to is multi-threaded,
  // disconnect_all() will block until all calls are serviced, meaning any
  // outstanding calls to OnVideoFrame will be done when this is done, and no
  // more calls will be serviced by this.
  // We do this explicitly instead of just letting the has_slots<> destructor
  // take care of it because we need to do this *before* video_renderers_ is
  // cleared by the destructor; otherwise we could mess with it while
  // OnVideoFrame is running.
  // We *don't* take capture_crit_ here since it could deadlock with the lock
  // taken by the video frame signal.
  disconnect_all();
}

CaptureRenderAdapter* CaptureRenderAdapter::Create(
    VideoCapturer* video_capturer) {
  if (!video_capturer) {
    return NULL;
  }
  CaptureRenderAdapter* return_value = new CaptureRenderAdapter(video_capturer);
  return_value->Init();  // Can't fail.
  return return_value;
}

bool CaptureRenderAdapter::AddRenderer(VideoRenderer* video_renderer) {
  if (!video_renderer) {
    return false;
  }
  rtc::CritScope cs(&capture_crit_);
  if (IsRendererRegistered(*video_renderer)) {
    return false;
  }
  video_renderers_.push_back(VideoRendererInfo(video_renderer));
  return true;
}

bool CaptureRenderAdapter::RemoveRenderer(VideoRenderer* video_renderer) {
  if (!video_renderer) {
    return false;
  }
  rtc::CritScope cs(&capture_crit_);
  for (VideoRenderers::iterator iter = video_renderers_.begin();
       iter != video_renderers_.end(); ++iter) {
    if (video_renderer == iter->renderer) {
      video_renderers_.erase(iter);
      return true;
    }
  }
  return false;
}

void CaptureRenderAdapter::Init() {
  video_capturer_->SignalVideoFrame.connect(
      this,
      &CaptureRenderAdapter::OnVideoFrame);
}

void CaptureRenderAdapter::OnVideoFrame(VideoCapturer* capturer,
                                        const VideoFrame* video_frame) {
  rtc::CritScope cs(&capture_crit_);
  if (video_renderers_.empty()) {
    return;
  }
  MaybeSetRenderingSize(video_frame);

  for (VideoRenderers::iterator iter = video_renderers_.begin();
       iter != video_renderers_.end(); ++iter) {
    VideoRenderer* video_renderer = iter->renderer;
    video_renderer->RenderFrame(video_frame);
  }
}

// The renderer_crit_ lock needs to be taken when calling this function.
void CaptureRenderAdapter::MaybeSetRenderingSize(const VideoFrame* frame) {
  for (VideoRenderers::iterator iter = video_renderers_.begin();
       iter != video_renderers_.end(); ++iter) {
    const bool new_resolution = iter->render_width != frame->GetWidth() ||
        iter->render_height != frame->GetHeight();
    if (new_resolution) {
      if (iter->renderer->SetSize(static_cast<int>(frame->GetWidth()),
                                  static_cast<int>(frame->GetHeight()), 0)) {
        iter->render_width = frame->GetWidth();
        iter->render_height = frame->GetHeight();
      } else {
        LOG(LS_ERROR) << "Captured frame size not supported by renderer: " <<
            frame->GetWidth() << " x " << frame->GetHeight();
      }
    }
  }
}

// The renderer_crit_ lock needs to be taken when calling this function.
bool CaptureRenderAdapter::IsRendererRegistered(
    const VideoRenderer& video_renderer) const {
  for (VideoRenderers::const_iterator iter = video_renderers_.begin();
       iter != video_renderers_.end(); ++iter) {
    if (&video_renderer == iter->renderer) {
      return true;
    }
  }
  return false;
}

}  // namespace cricket
