blob: e81a0dc0250692f2015bbcd26b1eb4de3dd5f995 [file] [log] [blame]
// Copyright 2021 Google LLC
//
// 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
//
// https://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.
// -----------------------------------------------------------------------------
//
// AV1 lossy decoding.
#include <cassert>
#include "src/common/av1_common.h"
#include "src/common/global_params.h"
#include "src/dec/wp2_dec_i.h"
#include "src/utils/csp.h"
#include "src/utils/utils.h"
#include "src/wp2/decode.h"
#if defined(WP2_HAVE_AOM)
#include "aom/aom_decoder.h"
#include "aom/aomdx.h"
namespace WP2 {
//------------------------------------------------------------------------------
WP2Status Av1Decode(const BitstreamFeatures& features,
const DecoderConfig& config, const DataView& dec,
Tile* const tile) {
// Codec instanciation
const aom_codec_iface_t* const itf = aom_codec_av1_dx();
WP2_CHECK_OK(itf != nullptr, WP2_STATUS_VERSION_MISMATCH);
const aom_codec_dec_cfg cfg = {/*threads=*/1, tile->rect.width,
tile->rect.height, /*allow_lowbitdepth=*/1};
aom_codec_ctx_t codec;
WP2_CHECK_STATUS(MapAomStatus(aom_codec_dec_init(&codec, itf, &cfg, 0)));
Cleaner<aom_codec_ctx_t, aom_codec_err_t> codec_cleaner(&codec,
aom_codec_destroy);
// Decoding settings
WP2_CHECK_STATUS(
MapAomStatus(aom_codec_control(&codec, AV1_SET_SKIP_LOOP_FILTER)));
// Decoding
WP2_CHECK_STATUS(MapAomStatus(
aom_codec_decode(&codec, dec.bytes, dec.size, /*user_priv=*/NULL)));
aom_codec_iter_t iter = NULL;
aom_image_t* img = aom_codec_get_frame(&codec, &iter);
WP2_CHECK_OK(img != NULL, WP2_STATUS_BITSTREAM_ERROR);
YUVPlane ycbcr;
WP2_CHECK_STATUS(ycbcr.Resize(tile->rect.width, tile->rect.height, /*pad=*/1,
!features.is_opaque));
ycbcr.Y.From(img->planes[AOM_PLANE_Y], img->stride[AOM_PLANE_Y], -16);
ycbcr.U.From(img->planes[AOM_PLANE_U], img->stride[AOM_PLANE_U], -128);
ycbcr.V.From(img->planes[AOM_PLANE_V], img->stride[AOM_PLANE_V], -128);
if (!ycbcr.A.IsEmpty()) {
// Alpha should be handled but in the meantime it is set to opaque.
ycbcr.A.Fill(kAlphaMax);
}
WP2_CHECK_STATUS(MapAomStatus(codec_cleaner.Destruct()));
// Wrap up
// YCbCr->RGB matrix from http://www.mir.com/DMG/ycbcr.html (x 1<<12),
// [16:235/240]->[0:255] range increase included.
constexpr int16_t kYCbCrToRGBMatrix[9] = {4769, 0, 6537, 4769, -1605,
-3330, 4769, 8263, 0};
constexpr uint32_t kYCbCrToRGBShift = 12;
tile->output_is_yuv = false;
WP2_CHECK_STATUS(ycbcr.Export(CSPMtx(kYCbCrToRGBMatrix, kYCbCrToRGBShift),
/*resize_if_needed=*/false, &tile->rgb_output));
WP2_CHECK_STATUS(tile->row_progress.AdvanceBy(tile->rect.height));
return WP2_STATUS_OK;
}
// -----------------------------------------------------------------------------
} // namespace WP2
#else
namespace WP2 {
WP2Status Av1Decode(const BitstreamFeatures&, const DecoderConfig&,
const DataView&, Tile* const) {
fprintf(stderr, "Error: libwebp2 was not built with libaom.\n");
return WP2_STATUS_UNSUPPORTED_FEATURE;
}
} // namespace WP2
#endif // defined(WP2_HAVE_AOM)