/*
 * Copyright (C) 2012 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. OR
 * CONTRIBUTORS 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 "platform/graphics/ImageFrameGenerator.h"

#include "SkData.h"
#include "platform/TraceEvent.h"
#include "platform/graphics/ImageDecodingStore.h"
#include "platform/image-decoders/ImageDecoder.h"
#include "third_party/skia/include/core/SkYUVSizeInfo.h"
#include "wtf/PtrUtil.h"
#include <memory>

namespace blink {

static bool compatibleInfo(const SkImageInfo& src, const SkImageInfo& dst) {
  if (src == dst)
    return true;

  // It is legal to write kOpaque_SkAlphaType pixels into a kPremul_SkAlphaType
  // buffer. This can happen when DeferredImageDecoder allocates an
  // kOpaque_SkAlphaType image generator based on cached frame info, while the
  // ImageFrame-allocated dest bitmap stays kPremul_SkAlphaType.
  if (src.alphaType() == kOpaque_SkAlphaType &&
      dst.alphaType() == kPremul_SkAlphaType) {
    const SkImageInfo& tmp = src.makeAlphaType(kPremul_SkAlphaType);
    return tmp == dst;
  }

  return false;
}

// Creates a SkPixelRef such that the memory for pixels is given by an external
// body. This is used to write directly to the memory given by Skia during
// decoding.
class ExternalMemoryAllocator final : public SkBitmap::Allocator {
  USING_FAST_MALLOC(ExternalMemoryAllocator);
  WTF_MAKE_NONCOPYABLE(ExternalMemoryAllocator);

 public:
  ExternalMemoryAllocator(const SkImageInfo& info,
                          void* pixels,
                          size_t rowBytes)
      : m_info(info), m_pixels(pixels), m_rowBytes(rowBytes) {}

  bool allocPixelRef(SkBitmap* dst, SkColorTable* ctable) override {
    const SkImageInfo& info = dst->info();
    if (kUnknown_SkColorType == info.colorType())
      return false;

    if (!compatibleInfo(m_info, info) || m_rowBytes != dst->rowBytes())
      return false;

    if (!dst->installPixels(info, m_pixels, m_rowBytes))
      return false;
    dst->lockPixels();
    return true;
  }

 private:
  SkImageInfo m_info;
  void* m_pixels;
  size_t m_rowBytes;
};

static bool updateYUVComponentSizes(ImageDecoder* decoder,
                                    SkISize componentSizes[3],
                                    size_t componentWidthBytes[3]) {
  if (!decoder->canDecodeToYUV())
    return false;

  IntSize size = decoder->decodedYUVSize(0);
  componentSizes[0].set(size.width(), size.height());
  componentWidthBytes[0] = decoder->decodedYUVWidthBytes(0);
  size = decoder->decodedYUVSize(1);
  componentSizes[1].set(size.width(), size.height());
  componentWidthBytes[1] = decoder->decodedYUVWidthBytes(1);
  size = decoder->decodedYUVSize(2);
  componentSizes[2].set(size.width(), size.height());
  componentWidthBytes[2] = decoder->decodedYUVWidthBytes(2);
  return true;
}

ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize,
                                         bool isMultiFrame)
    : m_fullSize(fullSize),
      m_isMultiFrame(isMultiFrame),
      m_decodeFailed(false),
      m_yuvDecodingFailed(false),
      m_frameCount(0) {}

ImageFrameGenerator::~ImageFrameGenerator() {
  ImageDecodingStore::instance().removeCacheIndexedByGenerator(this);
}

bool ImageFrameGenerator::decodeAndScale(SegmentReader* data,
                                         bool allDataReceived,
                                         size_t index,
                                         const SkImageInfo& info,
                                         void* pixels,
                                         size_t rowBytes) {
  if (m_decodeFailed)
    return false;

  TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "frame index",
               static_cast<int>(index));

  // This implementation does not support scaling so check the requested size.
  SkISize scaledSize = SkISize::Make(info.width(), info.height());
  ASSERT(m_fullSize == scaledSize);

  // It is okay to allocate ref-counted ExternalMemoryAllocator on the stack,
  // because 1) it contains references to memory that will be invalid after
  // returning (i.e. a pointer to |pixels|) and therefore 2) should not live
  // longer than the call to the current method.
  ExternalMemoryAllocator externalAllocator(info, pixels, rowBytes);
  SkBitmap bitmap = tryToResumeDecode(data, allDataReceived, index, scaledSize,
                                      &externalAllocator);
  DCHECK(externalAllocator.unique());  // Verify we have the only ref-count.

  if (bitmap.isNull())
    return false;

  // Check to see if the decoder has written directly to the pixel memory
  // provided. If not, make a copy.
  ASSERT(bitmap.width() == scaledSize.width());
  ASSERT(bitmap.height() == scaledSize.height());
  SkAutoLockPixels bitmapLock(bitmap);
  if (bitmap.getPixels() != pixels)
    return bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes);
  return true;
}

bool ImageFrameGenerator::decodeToYUV(SegmentReader* data,
                                      size_t index,
                                      const SkISize componentSizes[3],
                                      void* planes[3],
                                      const size_t rowBytes[3]) {
  // TODO (scroggo): The only interesting thing this uses from the
  // ImageFrameGenerator is m_decodeFailed. Move this into
  // DecodingImageGenerator, which is the only class that calls it.
  if (m_decodeFailed)
    return false;

  TRACE_EVENT1("blink", "ImageFrameGenerator::decodeToYUV", "frame index",
               static_cast<int>(index));

  if (!planes || !planes[0] || !planes[1] || !planes[2] || !rowBytes ||
      !rowBytes[0] || !rowBytes[1] || !rowBytes[2]) {
    return false;
  }

  std::unique_ptr<ImageDecoder> decoder =
      ImageDecoder::create(data, true, ImageDecoder::AlphaPremultiplied,
                           ImageDecoder::GammaAndColorProfileApplied);
  // getYUVComponentSizes was already called and was successful, so
  // ImageDecoder::create must succeed.
  ASSERT(decoder);

  std::unique_ptr<ImagePlanes> imagePlanes =
      wrapUnique(new ImagePlanes(planes, rowBytes));
  decoder->setImagePlanes(std::move(imagePlanes));

  ASSERT(decoder->canDecodeToYUV());

  if (decoder->decodeToYUV()) {
    setHasAlpha(0, false);  // YUV is always opaque
    return true;
  }

  ASSERT(decoder->failed());
  m_yuvDecodingFailed = true;
  return false;
}

SkBitmap ImageFrameGenerator::tryToResumeDecode(
    SegmentReader* data,
    bool allDataReceived,
    size_t index,
    const SkISize& scaledSize,
    SkBitmap::Allocator* allocator) {
  TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecode", "frame index",
               static_cast<int>(index));

  ImageDecoder* decoder = 0;

  // Lock the mutex, so only one thread can use the decoder at once.
  MutexLocker lock(m_decodeMutex);
  const bool resumeDecoding =
      ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
  ASSERT(!resumeDecoding || decoder);

  SkBitmap fullSizeImage;
  bool complete =
      decode(data, allDataReceived, index, &decoder, &fullSizeImage, allocator);

  if (!decoder)
    return SkBitmap();

  // If we are not resuming decoding that means the decoder is freshly
  // created and we have ownership. If we are resuming decoding then
  // the decoder is owned by ImageDecodingStore.
  std::unique_ptr<ImageDecoder> decoderContainer;
  if (!resumeDecoding)
    decoderContainer = wrapUnique(decoder);

  if (fullSizeImage.isNull()) {
    // If decoding has failed, we can save work in the future by
    // ignoring further requests to decode the image.
    m_decodeFailed = decoder->failed();
    if (resumeDecoding)
      ImageDecodingStore::instance().unlockDecoder(this, decoder);
    return SkBitmap();
  }

  bool removeDecoder = false;
  if (complete) {
    // Free as much memory as possible.  For single-frame images, we can
    // just delete the decoder entirely.  For multi-frame images, we keep
    // the decoder around in order to preserve decoded information such as
    // the required previous frame indexes, but if we've reached the last
    // frame we can at least delete all the cached frames.  (If we were to
    // do this before reaching the last frame, any subsequent requested
    // frames which relied on the current frame would trigger extra
    // re-decoding of all frames in the dependency chain.)
    if (!m_isMultiFrame)
      removeDecoder = true;
    else if (index == m_frameCount - 1)
      decoder->clearCacheExceptFrame(kNotFound);
  }

  if (resumeDecoding) {
    if (removeDecoder)
      ImageDecodingStore::instance().removeDecoder(this, decoder);
    else
      ImageDecodingStore::instance().unlockDecoder(this, decoder);
  } else if (!removeDecoder) {
    ImageDecodingStore::instance().insertDecoder(this,
                                                 std::move(decoderContainer));
  }
  return fullSizeImage;
}

void ImageFrameGenerator::setHasAlpha(size_t index, bool hasAlpha) {
  MutexLocker lock(m_alphaMutex);
  if (index >= m_hasAlpha.size()) {
    const size_t oldSize = m_hasAlpha.size();
    m_hasAlpha.resize(index + 1);
    for (size_t i = oldSize; i < m_hasAlpha.size(); ++i)
      m_hasAlpha[i] = true;
  }
  m_hasAlpha[index] = hasAlpha;
}

bool ImageFrameGenerator::decode(SegmentReader* data,
                                 bool allDataReceived,
                                 size_t index,
                                 ImageDecoder** decoder,
                                 SkBitmap* bitmap,
                                 SkBitmap::Allocator* allocator) {
  ASSERT(m_decodeMutex.locked());
  TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width",
               m_fullSize.width(), "height", m_fullSize.height());

  // Try to create an ImageDecoder if we are not given one.
  ASSERT(decoder);
  bool newDecoder = false;
  bool shouldCallSetData = true;
  if (!*decoder) {
    newDecoder = true;
    if (m_imageDecoderFactory)
      *decoder = m_imageDecoderFactory->create().release();

    if (!*decoder) {
      *decoder = ImageDecoder::create(data, allDataReceived,
                                      ImageDecoder::AlphaPremultiplied,
                                      ImageDecoder::GammaAndColorProfileApplied)
                     .release();
      // The newly created decoder just grabbed the data.  No need to reset it.
      shouldCallSetData = false;
    }

    if (!*decoder)
      return false;
  }

  if (!m_isMultiFrame && newDecoder && allDataReceived) {
    // If we're using an external memory allocator that means we're decoding
    // directly into the output memory and we can save one memcpy.
    ASSERT(allocator);
    (*decoder)->setMemoryAllocator(allocator);
  }

  if (shouldCallSetData)
    (*decoder)->setData(data, allDataReceived);
  ImageFrame* frame = (*decoder)->frameBufferAtIndex(index);

  // For multi-frame image decoders, we need to know how many frames are
  // in that image in order to release the decoder when all frames are
  // decoded. frameCount() is reliable only if all data is received and set in
  // decoder, particularly with GIF.
  if (allDataReceived)
    m_frameCount = (*decoder)->frameCount();

  (*decoder)->setData(PassRefPtr<SegmentReader>(nullptr),
                      false);  // Unref SegmentReader from ImageDecoder.
  (*decoder)->clearCacheExceptFrame(index);
  (*decoder)->setMemoryAllocator(0);

  if (!frame || frame->getStatus() == ImageFrame::FrameEmpty)
    return false;

  // A cache object is considered complete if we can decode a complete frame.
  // Or we have received all data. The image might not be fully decoded in
  // the latter case.
  const bool isDecodeComplete =
      frame->getStatus() == ImageFrame::FrameComplete || allDataReceived;

  SkBitmap fullSizeBitmap = frame->bitmap();
  if (!fullSizeBitmap.isNull()) {
    ASSERT(fullSizeBitmap.width() == m_fullSize.width() &&
           fullSizeBitmap.height() == m_fullSize.height());
    setHasAlpha(index, !fullSizeBitmap.isOpaque());
  }

  *bitmap = fullSizeBitmap;
  return isDecodeComplete;
}

bool ImageFrameGenerator::hasAlpha(size_t index) {
  MutexLocker lock(m_alphaMutex);
  if (index < m_hasAlpha.size())
    return m_hasAlpha[index];
  return true;
}

bool ImageFrameGenerator::getYUVComponentSizes(SegmentReader* data,
                                               SkYUVSizeInfo* sizeInfo) {
  TRACE_EVENT2("blink", "ImageFrameGenerator::getYUVComponentSizes", "width",
               m_fullSize.width(), "height", m_fullSize.height());

  if (m_yuvDecodingFailed)
    return false;

  std::unique_ptr<ImageDecoder> decoder =
      ImageDecoder::create(data, true, ImageDecoder::AlphaPremultiplied,
                           ImageDecoder::GammaAndColorProfileApplied);
  if (!decoder)
    return false;

  // Setting a dummy ImagePlanes object signals to the decoder that we want to
  // do YUV decoding.
  std::unique_ptr<ImagePlanes> dummyImagePlanes = wrapUnique(new ImagePlanes);
  decoder->setImagePlanes(std::move(dummyImagePlanes));

  return updateYUVComponentSizes(decoder.get(), sizeInfo->fSizes,
                                 sizeInfo->fWidthBytes);
}

}  // namespace blink
