// Copyright 2016 Google Inc. 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 "cobalt/loader/image/webp_image_decoder.h"

#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "cobalt/loader/image/animated_webp_image.h"
#include "starboard/memory.h"

namespace cobalt {
namespace loader {
namespace image {

WEBPImageDecoder::WEBPImageDecoder(
    render_tree::ResourceProvider* resource_provider)
    : ImageDataDecoder(resource_provider),
      internal_decoder_(NULL),
      has_animation_(false) {
  TRACE_EVENT0("cobalt::loader::image", "WEBPImageDecoder::WEBPImageDecoder()");
  // Initialize the configuration as empty.
  WebPInitDecoderConfig(&config_);
  // Skip the in-loop filtering.
  config_.options.bypass_filtering = 1;
  // Use faster pointwise upsampler.
  config_.options.no_fancy_upsampling = 1;
  // Don't use multi-threaded decoding.
  config_.options.use_threads = 0;
  // Discard enhancement layer.
  config_.options.no_enhancement = 1;
}

WEBPImageDecoder::~WEBPImageDecoder() {
  TRACE_EVENT0("cobalt::loader::image",
               "WEBPImageDecoder::~WEBPImageDecoder()");
  DeleteInternalDecoder();
}

uint8_t* WEBPImageDecoder::GetOriginalMemory() {
  return config_.output.u.RGBA.rgba;
}

size_t WEBPImageDecoder::DecodeChunkInternal(const uint8* data,
                                             size_t input_byte) {
  TRACE_EVENT0("cobalt::loader::image",
               "WEBPImageDecoder::DecodeChunkInternal()");
  if (state() == kWaitingForHeader) {
    if (!ReadHeader(data, input_byte)) {
      return 0;
    }

    if (!config_.input.has_animation) {
      if (!AllocateImageData(
              math::Size(config_.input.width, config_.input.height),
              !!config_.input.has_alpha)) {
        return 0;
      }
      if (!CreateInternalDecoder(!!config_.input.has_alpha)) {
        return 0;
      }
    } else {
      has_animation_ = true;
      animated_webp_image_ = new AnimatedWebPImage(
          math::Size(config_.input.width, config_.input.height),
          !!config_.input.has_alpha, pixel_format(), resource_provider());
    }
    set_state(kReadLines);
  }

  if (state() == kReadLines) {
    if (!config_.input.has_animation) {
      // Copies and decodes the next available data. Returns VP8_STATUS_OK when
      // the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when
      // more data is expected. Returns error in other cases.
      VP8StatusCode status = WebPIAppend(internal_decoder_, data, input_byte);
      if (status == VP8_STATUS_OK) {
        DCHECK(image_data());
        DCHECK(config_.output.u.RGBA.rgba);
        SbMemoryCopy(image_data()->GetMemory(), config_.output.u.RGBA.rgba,
                     config_.output.u.RGBA.size);
        set_state(kDone);
      } else if (status != VP8_STATUS_SUSPENDED) {
        DLOG(ERROR) << "WebPIAppend error, status code: " << status;
        DeleteInternalDecoder();
        set_state(kError);
      }
    } else {
      animated_webp_image_->AppendChunk(data, input_byte);
    }
  }

  return input_byte;
}

void WEBPImageDecoder::FinishInternal() {
  if (config_.input.has_animation) {
    set_state(kDone);
  }
}

bool WEBPImageDecoder::ReadHeader(const uint8* data, size_t size) {
  TRACE_EVENT0("cobalt::loader::image", "WEBPImageDecoder::ReadHeader()");
  // Retrieve features from the bitstream. The *features structure is filled
  // with information gathered from the bitstream.
  // Returns VP8_STATUS_OK when the features are successfully retrieved. Returns
  // VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the
  // features from headers. Returns error in other cases.
  VP8StatusCode status = WebPGetFeatures(data, size, &config_.input);
  if (status == VP8_STATUS_OK) {
    return true;
  } else if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
    // Data is not enough for decoding the header.
    return false;
  } else {
    DLOG(ERROR) << "WebPGetFeatures error, status code: " << status;
    set_state(kError);
    return false;
  }
}

bool WEBPImageDecoder::CreateInternalDecoder(bool has_alpha) {
  TRACE_EVENT0("cobalt::loader::image",
               "WEBPImageDecoder::CreateInternalDecoder()");
  config_.output.colorspace = pixel_format() == render_tree::kPixelFormatRGBA8
                                  ? (has_alpha ? MODE_rgbA : MODE_RGBA)
                                  : (has_alpha ? MODE_bgrA : MODE_BGRA);
  config_.output.u.RGBA.stride = image_data()->GetDescriptor().pitch_in_bytes;
  config_.output.u.RGBA.size =
      static_cast<size_t>(config_.output.u.RGBA.stride *
                          image_data()->GetDescriptor().size.height());
  // We don't use image buffer as the decoding buffer because libwebp will read
  // from it while we assume that our image buffer is write only.
  config_.output.is_external_memory = 0;

  // Instantiate a new incremental decoder object with the requested
  // configuration.
  internal_decoder_ = WebPIDecode(NULL, 0, &config_);

  if (internal_decoder_ == NULL) {
    DLOG(WARNING) << "Create internal WEBP decoder failed.";
    set_state(kError);
    return false;
  }
  return true;
}

void WEBPImageDecoder::DeleteInternalDecoder() {
  TRACE_EVENT0("cobalt::loader::image",
               "WEBPImageDecoder::DeleteInternalDecoder()");
  if (internal_decoder_) {
    // Deletes the WebPIDecoder object and associated memory. Must always be
    // called if WebPIDecode succeeded.
    WebPIDelete(internal_decoder_);
    internal_decoder_ = NULL;
    WebPFreeDecBuffer(&config_.output);
  }
}

}  // namespace image
}  // namespace loader
}  // namespace cobalt
