// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/raspi/shared/open_max/open_max_component_base.h"

#include <algorithm>

#include "starboard/configuration.h"
#include "starboard/once.h"

namespace starboard {
namespace raspi {
namespace shared {
namespace open_max {

namespace {

const int kInvalidPort = -1;

const OMX_INDEXTYPE kPortTypes[] = {
    OMX_IndexParamAudioInit, OMX_IndexParamVideoInit, OMX_IndexParamImageInit,
    OMX_IndexParamOtherInit};

SbOnceControl s_open_max_initialization_once = SB_ONCE_INITIALIZER;

void DoInitializeOpenMax() {
  OMX_ERRORTYPE error = OMX_Init();
  SB_DCHECK(error == OMX_ErrorNone);
}

void InitializeOpenMax() {
  bool initialized =
      SbOnce(&s_open_max_initialization_once, DoInitializeOpenMax);
  SB_DCHECK(initialized);
}

}  // namespace

OpenMaxComponentBase::OpenMaxComponentBase(const char* name)
    : event_condition_variable_(mutex_),
      handle_(NULL),
      input_port_(kInvalidPort),
      output_port_(kInvalidPort) {
  InitializeOpenMax();

  OMX_CALLBACKTYPE callbacks;
  callbacks.EventHandler = OpenMaxComponentBase::EventHandler;
  callbacks.EmptyBufferDone = OpenMaxComponentBase::EmptyBufferDone;
  callbacks.FillBufferDone = OpenMaxComponentBase::FillBufferDone;

  OMX_ERRORTYPE error =
      OMX_GetHandle(&handle_, const_cast<char*>(name), this, &callbacks);
  SB_DCHECK(error == OMX_ErrorNone);

  for (size_t i = 0; i < SB_ARRAY_SIZE(kPortTypes); ++i) {
    OMX_PORT_PARAM_TYPE port;
    port.nSize = sizeof(OMX_PORT_PARAM_TYPE);
    port.nVersion.nVersion = OMX_VERSION;

    error = OMX_GetParameter(handle_, kPortTypes[i], &port);
    if (error == OMX_ErrorNone && port.nPorts == 2) {
      input_port_ = port.nStartPortNumber;
      output_port_ = input_port_ + 1;
      SendCommandAndWaitForCompletion(OMX_CommandPortDisable, input_port_);
      SendCommandAndWaitForCompletion(OMX_CommandPortDisable, output_port_);
      break;
    }
  }
  SB_CHECK(input_port_ != kInvalidPort);
  SB_CHECK(output_port_ != kInvalidPort);
  SB_DLOG(INFO) << "Opened \"" << name << "\" with port " << input_port_
                << " and " << output_port_;
}

OpenMaxComponentBase::~OpenMaxComponentBase() {
  if (!handle_) {
    return;
  }

  OMX_FreeHandle(handle_);
}

void OpenMaxComponentBase::SendCommand(OMX_COMMANDTYPE command, int param) {
  OMX_ERRORTYPE error = OMX_SendCommand(handle_, command, param, NULL);
  SB_DCHECK(error == OMX_ErrorNone);
}

void OpenMaxComponentBase::WaitForCommandCompletion() {
  for (;;) {
    ScopedLock scoped_lock(mutex_);
    for (EventDescriptions::iterator iter = event_descriptions_.begin();
         iter != event_descriptions_.end(); ++iter) {
      if (iter->event == OMX_EventCmdComplete) {
        event_descriptions_.erase(iter);
        return;
      }
      // Special case for OMX_CommandStateSet.
      if (iter->event == OMX_EventError && iter->data1 == OMX_ErrorSameState) {
        event_descriptions_.erase(iter);
        return;
      }
    }
    event_condition_variable_.Wait();
  }
}

void OpenMaxComponentBase::SendCommandAndWaitForCompletion(
    OMX_COMMANDTYPE command,
    int param) {
  SendCommand(command, param);
  WaitForCommandCompletion();
}

OMX_ERRORTYPE OpenMaxComponentBase::OnEvent(OMX_EVENTTYPE event,
                                            OMX_U32 data1,
                                            OMX_U32 data2,
                                            OMX_PTR event_data) {
  if (event == OMX_EventError && data1 != OMX_ErrorSameState) {
    OnErrorEvent(data1, data2, event_data);
    return OMX_ErrorNone;
  }

  if (event == OMX_EventPortSettingsChanged && data1 == output_port_) {
    OnOutputSettingChanged();
    return OMX_ErrorNone;
  }

  ScopedLock scoped_lock(mutex_);
  EventDescription event_desc;
  event_desc.event = event;
  event_desc.data1 = data1;
  event_desc.data2 = data2;
  event_desc.event_data = event_data;
  event_descriptions_.push_back(event_desc);
  event_condition_variable_.Signal();

  return OMX_ErrorNone;
}

// static
OMX_ERRORTYPE OpenMaxComponentBase::EventHandler(OMX_HANDLETYPE handle,
                                                 OMX_PTR app_data,
                                                 OMX_EVENTTYPE event,
                                                 OMX_U32 data1,
                                                 OMX_U32 data2,
                                                 OMX_PTR event_data) {
  SB_DCHECK(app_data != NULL);
  OpenMaxComponentBase* component =
      reinterpret_cast<OpenMaxComponentBase*>(app_data);
  SB_DCHECK(handle == component->handle_);

  return component->OnEvent(event, data1, data2, event_data);
}

// static
OMX_ERRORTYPE OpenMaxComponentBase::EmptyBufferDone(
    OMX_HANDLETYPE handle,
    OMX_PTR app_data,
    OMX_BUFFERHEADERTYPE* buffer) {
  SB_DCHECK(app_data != NULL);
  OpenMaxComponentBase* component =
      reinterpret_cast<OpenMaxComponentBase*>(app_data);
  SB_DCHECK(handle == component->handle_);

  return component->OnEmptyBufferDone(buffer);
}

// static
OMX_ERRORTYPE OpenMaxComponentBase::FillBufferDone(
    OMX_HANDLETYPE handle,
    OMX_PTR app_data,
    OMX_BUFFERHEADERTYPE* buffer) {
  SB_DCHECK(app_data != NULL);
  OpenMaxComponentBase* component =
      reinterpret_cast<OpenMaxComponentBase*>(app_data);
  SB_DCHECK(handle == component->handle_);

  component->OnFillBufferDone(buffer);

  return OMX_ErrorNone;
}

}  // namespace open_max
}  // namespace shared
}  // namespace raspi
}  // namespace starboard
