// Copyright 2017 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_image_decode_component.h"

#include <algorithm>

#include "starboard/configuration.h"
#include "starboard/memory.h"
#include "starboard/raspi/shared/open_max/decode_target_create.h"
#include "starboard/raspi/shared/open_max/decode_target_internal.h"
#include "starboard/thread.h"

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

namespace {

struct MimeToFormat {
  const char* mime_type;
  OMX_IMAGE_CODINGTYPE format;
};

const MimeToFormat kSupportedFormats[] = {
    {"image/jpeg", OMX_IMAGE_CodingJPEG},
    // The image decode component doesn't handle PNG very well.
    //   { "image/png", OMX_IMAGE_CodingPNG },
    // GIF decoding should work, but it has not been tested.
    //   { "image/gif", OMX_IMAGE_CodingGIF },
};

}  // namespace

OpenMaxImageDecodeComponent::OpenMaxImageDecodeComponent()
    : OpenMaxComponent("OMX.broadcom.image_decode"),
      state_(kStateIdle),
      graphics_context_provider_(NULL),
      target_(NULL),
      input_format_(OMX_IMAGE_CodingMax) {}

// static
OMX_IMAGE_CODINGTYPE OpenMaxImageDecodeComponent::GetCompressionFormat(
    const char* mime_type) {
  for (int index = 0; index < SB_ARRAY_SIZE_INT(kSupportedFormats); ++index) {
    if (strcmp(mime_type, kSupportedFormats[index].mime_type) == 0) {
      return kSupportedFormats[index].format;
    }
  }
  return OMX_IMAGE_CodingMax;
}

SbDecodeTarget OpenMaxImageDecodeComponent::Decode(
    SbDecodeTargetGraphicsContextProvider* provider,
    const char* mime_type,
    SbDecodeTargetFormat output_format,
    const void* data,
    int data_size) {
  SB_DCHECK(target_ == NULL);

  graphics_context_provider_ = provider;
  SetInputFormat(mime_type, output_format);

  // Start the component and enable the input port.
  Start();
  state_ = kStateInputReady;

  // Process the encoded data. This will call OnEnableOutputPort() when the
  // component is ready to start filling the output.
  int data_size_written = 0;
  for (;;) {
    int write_size = data_size - data_size_written;
    if (write_size > 0) {
      write_size =
          WriteData(reinterpret_cast<const uint8_t*>(data) + data_size_written,
                    write_size, kDataEOS, SbTimeGetMonotonicNow());
      SB_DCHECK(write_size >= 0);
      data_size_written += write_size;
    }
    int output_size = ProcessOutput();
    if (state_ == kStateDecodeDone) {
      break;
    } else if (write_size == 0 && output_size == 0) {
      // Wait for buffers to become available.
      SbThreadSleep(kSbTimeMillisecond);
    }
  }

  // Clean up.
  state_ = kStateIdle;
  CloseTunnel();
  return target_;
}

void OpenMaxImageDecodeComponent::SetInputFormat(const char* mime_type,
                                                 SbDecodeTargetFormat format) {
  OMXParam<OMX_IMAGE_PARAM_PORTFORMATTYPE, OMX_IndexParamImagePortFormat>
      port_format;
  GetInputPortParam(&port_format);
  input_format_ = GetCompressionFormat(mime_type);
  port_format.eCompressionFormat = input_format_;
  SB_DCHECK(port_format.eCompressionFormat != OMX_IMAGE_CodingMax);
  SetPortParam(port_format);
}

void OpenMaxImageDecodeComponent::SetOutputFormat(OMX_COLOR_FORMATTYPE format,
                                                  int width,
                                                  int height) {
  target_ = DecodeTargetCreate(graphics_context_provider_,
                               kSbDecodeTargetFormat1PlaneRGBA, width, height);
  target_->info.is_opaque =
      (input_format_ == OMX_IMAGE_CodingPNG) ? false : true;
  render_component_.SetOutputImage(target_->images[0]);
}

int OpenMaxImageDecodeComponent::ProcessOutput() {
  OMX_BUFFERHEADERTYPE* buffer = GetOutputBuffer();
  int output_size = 0;
  if (buffer) {
    SB_DCHECK(state_ == kStateOutputReady);
    bool is_end_of_stream = (buffer->nFlags & OMX_BUFFERFLAG_EOS) != 0;
    output_size = 1;  // Signal to caller that some data was processed.
    DropOutputBuffer(buffer);
    if (is_end_of_stream) {
      state_ = kStateDecodeDone;
    }
  }

  return output_size;
}

bool OpenMaxImageDecodeComponent::OnEnableOutputPort(
    OMXParamPortDefinition* port_definition) {
  if (port_definition->nPortIndex == output_port_) {
    // Our output port has been enabled. Tunnel to the egl render
    // component to decode into a texture.
    SB_DCHECK(state_ == kStateInputReady);
    render_component_.ForwardPortCallbacks(this);
    SetOutputComponent(&render_component_);
    state_ = kStateSetTunnelOutput;
    return false;
  } else if (state_ == kStateSetTunnelOutput) {
    // Tunnelled component's output port was just enabled.
    state_ = kStateOutputReady;
    return false;
  } else {
    // Got final settings for the tunnelled component's output port.
    SB_DCHECK(state_ == kStateOutputReady);
    SetOutputFormat(port_definition->format.video.eColorFormat,
                    port_definition->format.video.nFrameWidth,
                    port_definition->format.video.nFrameHeight);
    return false;
  }
}

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