blob: e095eb728cb2f9842afaed30efbb15627c99c756 [file] [log] [blame]
/*
* Copyright (C) 2021 Igalia S.L. 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 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 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 "config.h"
#if USE(AVIF)
#include "AVIFImageDecoder.h"
#include "AVIFImageReader.h"
namespace WebCore {
AVIFImageDecoder::AVIFImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
: ScalableImageDecoder(alphaOption, gammaAndColorProfileOption)
{
}
AVIFImageDecoder::~AVIFImageDecoder() = default;
RepetitionCount AVIFImageDecoder::repetitionCount() const
{
if (failed() || m_frameCount <= 1)
return RepetitionCountOnce;
return m_repetitionCount ? m_repetitionCount : RepetitionCountInfinite;
}
size_t AVIFImageDecoder::findFirstRequiredFrameToDecode(size_t frameIndex)
{
// The first frame doesn't depend on any other.
if (!frameIndex)
return 0;
size_t firstIncompleteFrame = frameIndex;
while (firstIncompleteFrame > 0) {
if (m_frameBufferCache[firstIncompleteFrame - 1].isComplete())
break;
--firstIncompleteFrame;
}
return firstIncompleteFrame;
}
ScalableImageDecoderFrame* AVIFImageDecoder::frameBufferAtIndex(size_t index)
{
const size_t imageCount = frameCount();
if (index >= imageCount)
return nullptr;
if ((m_frameBufferCache.size() > index) && m_frameBufferCache[index].isComplete())
return &m_frameBufferCache[index];
if (imageCount && m_frameBufferCache.size() != imageCount)
m_frameBufferCache.resize(imageCount);
for (size_t i = findFirstRequiredFrameToDecode(index); i <= index; ++i) {
if (m_frameBufferCache[i].isComplete())
continue;
decode(i, isAllDataReceived());
}
return &m_frameBufferCache[index];
}
bool AVIFImageDecoder::setFailed()
{
m_reader = nullptr;
return ScalableImageDecoder::setFailed();
}
bool AVIFImageDecoder::isComplete()
{
if (m_frameBufferCache.isEmpty())
return false;
for (auto& frameBuffer : m_frameBufferCache) {
if (!frameBuffer.isComplete())
return false;
}
return true;
}
void AVIFImageDecoder::tryDecodeSize(bool allDataReceived)
{
if (!m_reader)
m_reader = makeUnique<AVIFImageReader>(this);
if (!m_reader->parseHeader(*m_data, allDataReceived))
return;
m_frameCount = m_reader->imageCount();
// FIXME: The avif sequence image can repeat for non-integer times (e.g., 2.5 times)
// but ScalableImageDecoder accepts an integer only for the repetition count.
// https://github.com/AOMediaCodec/av1-avif/issues/73
m_repetitionCount = static_cast<RepetitionCount>(std::round(m_reader->repetitionCount()));
}
void AVIFImageDecoder::decode(size_t frameIndex, bool allDataReceived)
{
if (failed())
return;
ASSERT(m_reader);
m_reader->decodeFrame(frameIndex, m_frameBufferCache[frameIndex], *m_data);
if (allDataReceived && !m_frameBufferCache.isEmpty() && isComplete())
m_reader = nullptr;
}
}
#endif // USE(AVIF)