// libjingle
// Copyright 2011 Google Inc. All Rights Reserved
//
// 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.
//
// Implementation of CarbonVideoRenderer

#include "talk/session/phone/carbonvideorenderer.h"

#include "talk/base/logging.h"
#include "talk/session/phone/videocommon.h"
#include "talk/session/phone/videoframe.h"

namespace cricket {

CarbonVideoRenderer::CarbonVideoRenderer(int x, int y)
    : image_width_(0),
      image_height_(0),
      x_(x),
      y_(y),
      image_ref_(NULL),
      window_ref_(NULL) {
}

CarbonVideoRenderer::~CarbonVideoRenderer() {
  if (window_ref_) {
    DisposeWindow(window_ref_);
  }
}

// Called from the main event loop. All renderering needs to happen on
// the main thread.
OSStatus CarbonVideoRenderer::DrawEventHandler(EventHandlerCallRef handler,
                                               EventRef event,
                                               void* data) {
  OSStatus status = noErr;
  CarbonVideoRenderer* renderer = static_cast<CarbonVideoRenderer*>(data);
  if (renderer != NULL) {
    if (!renderer->DrawFrame()) {
      LOG(LS_ERROR) << "Failed to draw frame.";
    }
  }
  return status;
}

bool CarbonVideoRenderer::DrawFrame() {
  // Grab the image lock to make sure it is not changed why we'll draw it.
  talk_base::CritScope cs(&image_crit_);

  if (image_.get() == NULL) {
    // Nothing to draw, just return.
    return true;
  }
  int width = image_width_;
  int height = image_height_;
  CGDataProviderRef provider =
      CGDataProviderCreateWithData(NULL, image_.get(), width * height * 4,
                                   NULL);
  CGColorSpaceRef color_space_ref = CGColorSpaceCreateDeviceRGB();
  CGBitmapInfo bitmap_info = kCGBitmapByteOrderDefault;
  CGColorRenderingIntent rendering_intent = kCGRenderingIntentDefault;
  CGImageRef image_ref = CGImageCreate(width, height, 8, 32, width * 4,
                                       color_space_ref, bitmap_info, provider,
                                       NULL, false, rendering_intent);
  CGDataProviderRelease(provider);

  if (image_ref == NULL) {
    return false;
  }
  CGContextRef context;
  SetPortWindowPort(window_ref_);
  if (QDBeginCGContext(GetWindowPort(window_ref_), &context) != noErr) {
    CGImageRelease(image_ref);
    return false;
  }
  Rect window_bounds;
  GetWindowPortBounds(window_ref_, &window_bounds);

  // Anchor the image to the top left corner.
  int x = 0;
  int y = window_bounds.bottom - CGImageGetHeight(image_ref);
  CGRect dst_rect = CGRectMake(x, y, CGImageGetWidth(image_ref),
                               CGImageGetHeight(image_ref));
  CGContextDrawImage(context, dst_rect, image_ref);
  CGContextFlush(context);
  QDEndCGContext(GetWindowPort(window_ref_), &context);
  CGImageRelease(image_ref);
  return true;
}

bool CarbonVideoRenderer::SetSize(int width, int height, int reserved) {
  if (width != image_width_ || height != image_height_) {
    // Grab the image lock while changing its size.
    talk_base::CritScope cs(&image_crit_);
    image_width_ = width;
    image_height_ = height;
    image_.reset(new uint8[width * height * 4]);
    memset(image_.get(), 255, width * height * 4);
  }
  return true;
}

bool CarbonVideoRenderer::RenderFrame(const VideoFrame* frame) {
  if (!frame) {
    return false;
  }
  {
    // Grab the image lock so we are not trashing up the image being drawn.
    talk_base::CritScope cs(&image_crit_);
    frame->ConvertToRgbBuffer(cricket::FOURCC_ABGR,
                              image_.get(),
                              frame->GetWidth() * frame->GetHeight() * 4,
                              frame->GetWidth() * 4);
  }

  // Trigger a repaint event for the whole window.
  Rect bounds;
  InvalWindowRect(window_ref_, GetWindowPortBounds(window_ref_, &bounds));
  return true;
}

bool CarbonVideoRenderer::Initialize() {
  OSStatus err;
  WindowAttributes attributes =
      kWindowStandardDocumentAttributes |
      kWindowLiveResizeAttribute |
      kWindowFrameworkScaledAttribute |
      kWindowStandardHandlerAttribute;

  struct Rect bounds;
  bounds.top = y_;
  bounds.bottom = 480;
  bounds.left = x_;
  bounds.right = 640;
  err = CreateNewWindow(kDocumentWindowClass, attributes,
                        &bounds, &window_ref_);
  if (!window_ref_ || err != noErr) {
    LOG(LS_ERROR) << "CreateNewWindow failed, error code: " << err;
    return false;
  }
  static const EventTypeSpec event_spec = {
    kEventClassWindow,
    kEventWindowDrawContent
  };

  err = InstallWindowEventHandler(
      window_ref_,
      NewEventHandlerUPP(CarbonVideoRenderer::DrawEventHandler),
      GetEventTypeCount(event_spec),
      &event_spec,
      this,
      NULL);
  if (err != noErr) {
    LOG(LS_ERROR) << "Failed to install event handler, error code: " << err;
    return false;
  }
  SelectWindow(window_ref_);
  ShowWindow(window_ref_);
  return true;
}

}  // namespace cricket
