mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-12 19:18:44 +02:00
f9e7a2f95a
This also adds support to avconv (which is trivial due to the new hwaccel API being generic enough). The new decoder setup code in dxva2.c is significantly based on work by Steve Lhomme <robux4@gmail.com>, but with heavy changes/rewrites. Signed-off-by: Diego Biurrun <diego@biurrun.de>
3103 lines
117 KiB
C
3103 lines
117 KiB
C
/*
|
|
* HEVC video decoder
|
|
*
|
|
* Copyright (C) 2012 - 2013 Guillaume Martres
|
|
* Copyright (C) 2012 - 2013 Mickael Raulet
|
|
* Copyright (C) 2012 - 2013 Gildas Cocherel
|
|
* Copyright (C) 2012 - 2013 Wassim Hamidouche
|
|
*
|
|
* This file is part of Libav.
|
|
*
|
|
* Libav is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* Libav is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with Libav; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "libavutil/attributes.h"
|
|
#include "libavutil/common.h"
|
|
#include "libavutil/display.h"
|
|
#include "libavutil/internal.h"
|
|
#include "libavutil/md5.h"
|
|
#include "libavutil/opt.h"
|
|
#include "libavutil/pixdesc.h"
|
|
#include "libavutil/stereo3d.h"
|
|
|
|
#include "bswapdsp.h"
|
|
#include "bytestream.h"
|
|
#include "cabac_functions.h"
|
|
#include "golomb_legacy.h"
|
|
#include "hevc.h"
|
|
#include "hevc_data.h"
|
|
#include "hevcdec.h"
|
|
#include "profiles.h"
|
|
|
|
const uint8_t ff_hevc_qpel_extra_before[4] = { 0, 3, 3, 3 };
|
|
const uint8_t ff_hevc_qpel_extra_after[4] = { 0, 4, 4, 4 };
|
|
const uint8_t ff_hevc_qpel_extra[4] = { 0, 7, 7, 7 };
|
|
|
|
static const uint8_t scan_1x1[1] = { 0 };
|
|
|
|
static const uint8_t horiz_scan2x2_x[4] = { 0, 1, 0, 1 };
|
|
|
|
static const uint8_t horiz_scan2x2_y[4] = { 0, 0, 1, 1 };
|
|
|
|
static const uint8_t horiz_scan4x4_x[16] = {
|
|
0, 1, 2, 3,
|
|
0, 1, 2, 3,
|
|
0, 1, 2, 3,
|
|
0, 1, 2, 3,
|
|
};
|
|
|
|
static const uint8_t horiz_scan4x4_y[16] = {
|
|
0, 0, 0, 0,
|
|
1, 1, 1, 1,
|
|
2, 2, 2, 2,
|
|
3, 3, 3, 3,
|
|
};
|
|
|
|
static const uint8_t horiz_scan8x8_inv[8][8] = {
|
|
{ 0, 1, 2, 3, 16, 17, 18, 19, },
|
|
{ 4, 5, 6, 7, 20, 21, 22, 23, },
|
|
{ 8, 9, 10, 11, 24, 25, 26, 27, },
|
|
{ 12, 13, 14, 15, 28, 29, 30, 31, },
|
|
{ 32, 33, 34, 35, 48, 49, 50, 51, },
|
|
{ 36, 37, 38, 39, 52, 53, 54, 55, },
|
|
{ 40, 41, 42, 43, 56, 57, 58, 59, },
|
|
{ 44, 45, 46, 47, 60, 61, 62, 63, },
|
|
};
|
|
|
|
static const uint8_t diag_scan2x2_x[4] = { 0, 0, 1, 1 };
|
|
|
|
static const uint8_t diag_scan2x2_y[4] = { 0, 1, 0, 1 };
|
|
|
|
static const uint8_t diag_scan2x2_inv[2][2] = {
|
|
{ 0, 2, },
|
|
{ 1, 3, },
|
|
};
|
|
|
|
static const uint8_t diag_scan4x4_inv[4][4] = {
|
|
{ 0, 2, 5, 9, },
|
|
{ 1, 4, 8, 12, },
|
|
{ 3, 7, 11, 14, },
|
|
{ 6, 10, 13, 15, },
|
|
};
|
|
|
|
static const uint8_t diag_scan8x8_inv[8][8] = {
|
|
{ 0, 2, 5, 9, 14, 20, 27, 35, },
|
|
{ 1, 4, 8, 13, 19, 26, 34, 42, },
|
|
{ 3, 7, 12, 18, 25, 33, 41, 48, },
|
|
{ 6, 11, 17, 24, 32, 40, 47, 53, },
|
|
{ 10, 16, 23, 31, 39, 46, 52, 57, },
|
|
{ 15, 22, 30, 38, 45, 51, 56, 60, },
|
|
{ 21, 29, 37, 44, 50, 55, 59, 62, },
|
|
{ 28, 36, 43, 49, 54, 58, 61, 63, },
|
|
};
|
|
|
|
/**
|
|
* NOTE: Each function hls_foo correspond to the function foo in the
|
|
* specification (HLS stands for High Level Syntax).
|
|
*/
|
|
|
|
/**
|
|
* Section 5.7
|
|
*/
|
|
|
|
/* free everything allocated by pic_arrays_init() */
|
|
static void pic_arrays_free(HEVCContext *s)
|
|
{
|
|
av_freep(&s->sao);
|
|
av_freep(&s->deblock);
|
|
|
|
av_freep(&s->skip_flag);
|
|
av_freep(&s->tab_ct_depth);
|
|
|
|
av_freep(&s->tab_ipm);
|
|
av_freep(&s->cbf_luma);
|
|
av_freep(&s->is_pcm);
|
|
|
|
av_freep(&s->qp_y_tab);
|
|
av_freep(&s->tab_slice_address);
|
|
av_freep(&s->filter_slice_edges);
|
|
|
|
av_freep(&s->horizontal_bs);
|
|
av_freep(&s->vertical_bs);
|
|
|
|
av_buffer_pool_uninit(&s->tab_mvf_pool);
|
|
av_buffer_pool_uninit(&s->rpl_tab_pool);
|
|
}
|
|
|
|
/* allocate arrays that depend on frame dimensions */
|
|
static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps)
|
|
{
|
|
int log2_min_cb_size = sps->log2_min_cb_size;
|
|
int width = sps->width;
|
|
int height = sps->height;
|
|
int pic_size_in_ctb = ((width >> log2_min_cb_size) + 1) *
|
|
((height >> log2_min_cb_size) + 1);
|
|
int ctb_count = sps->ctb_width * sps->ctb_height;
|
|
int min_pu_size = sps->min_pu_width * sps->min_pu_height;
|
|
|
|
s->bs_width = width >> 3;
|
|
s->bs_height = height >> 3;
|
|
|
|
s->sao = av_mallocz_array(ctb_count, sizeof(*s->sao));
|
|
s->deblock = av_mallocz_array(ctb_count, sizeof(*s->deblock));
|
|
if (!s->sao || !s->deblock)
|
|
goto fail;
|
|
|
|
s->skip_flag = av_malloc(pic_size_in_ctb);
|
|
s->tab_ct_depth = av_malloc(sps->min_cb_height * sps->min_cb_width);
|
|
if (!s->skip_flag || !s->tab_ct_depth)
|
|
goto fail;
|
|
|
|
s->cbf_luma = av_malloc(sps->min_tb_width * sps->min_tb_height);
|
|
s->tab_ipm = av_mallocz(min_pu_size);
|
|
s->is_pcm = av_malloc(min_pu_size);
|
|
if (!s->tab_ipm || !s->cbf_luma || !s->is_pcm)
|
|
goto fail;
|
|
|
|
s->filter_slice_edges = av_malloc(ctb_count);
|
|
s->tab_slice_address = av_malloc(pic_size_in_ctb *
|
|
sizeof(*s->tab_slice_address));
|
|
s->qp_y_tab = av_malloc(pic_size_in_ctb *
|
|
sizeof(*s->qp_y_tab));
|
|
if (!s->qp_y_tab || !s->filter_slice_edges || !s->tab_slice_address)
|
|
goto fail;
|
|
|
|
s->horizontal_bs = av_mallocz(2 * s->bs_width * (s->bs_height + 1));
|
|
s->vertical_bs = av_mallocz(2 * s->bs_width * (s->bs_height + 1));
|
|
if (!s->horizontal_bs || !s->vertical_bs)
|
|
goto fail;
|
|
|
|
s->tab_mvf_pool = av_buffer_pool_init(min_pu_size * sizeof(MvField),
|
|
av_buffer_alloc);
|
|
s->rpl_tab_pool = av_buffer_pool_init(ctb_count * sizeof(RefPicListTab),
|
|
av_buffer_allocz);
|
|
if (!s->tab_mvf_pool || !s->rpl_tab_pool)
|
|
goto fail;
|
|
|
|
return 0;
|
|
|
|
fail:
|
|
pic_arrays_free(s);
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
|
|
static void pred_weight_table(HEVCContext *s, GetBitContext *gb)
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
uint8_t luma_weight_l0_flag[16];
|
|
uint8_t chroma_weight_l0_flag[16];
|
|
uint8_t luma_weight_l1_flag[16];
|
|
uint8_t chroma_weight_l1_flag[16];
|
|
|
|
s->sh.luma_log2_weight_denom = av_clip(get_ue_golomb_long(gb), 0, 7);
|
|
if (s->ps.sps->chroma_format_idc != 0) {
|
|
int delta = get_se_golomb(gb);
|
|
s->sh.chroma_log2_weight_denom = av_clip(s->sh.luma_log2_weight_denom + delta, 0, 7);
|
|
}
|
|
|
|
for (i = 0; i < s->sh.nb_refs[L0]; i++) {
|
|
luma_weight_l0_flag[i] = get_bits1(gb);
|
|
if (!luma_weight_l0_flag[i]) {
|
|
s->sh.luma_weight_l0[i] = 1 << s->sh.luma_log2_weight_denom;
|
|
s->sh.luma_offset_l0[i] = 0;
|
|
}
|
|
}
|
|
if (s->ps.sps->chroma_format_idc != 0) { // FIXME: invert "if" and "for"
|
|
for (i = 0; i < s->sh.nb_refs[L0]; i++)
|
|
chroma_weight_l0_flag[i] = get_bits1(gb);
|
|
} else {
|
|
for (i = 0; i < s->sh.nb_refs[L0]; i++)
|
|
chroma_weight_l0_flag[i] = 0;
|
|
}
|
|
for (i = 0; i < s->sh.nb_refs[L0]; i++) {
|
|
if (luma_weight_l0_flag[i]) {
|
|
int delta_luma_weight_l0 = get_se_golomb(gb);
|
|
s->sh.luma_weight_l0[i] = (1 << s->sh.luma_log2_weight_denom) + delta_luma_weight_l0;
|
|
s->sh.luma_offset_l0[i] = get_se_golomb(gb);
|
|
}
|
|
if (chroma_weight_l0_flag[i]) {
|
|
for (j = 0; j < 2; j++) {
|
|
int delta_chroma_weight_l0 = get_se_golomb(gb);
|
|
int delta_chroma_offset_l0 = get_se_golomb(gb);
|
|
s->sh.chroma_weight_l0[i][j] = (1 << s->sh.chroma_log2_weight_denom) + delta_chroma_weight_l0;
|
|
s->sh.chroma_offset_l0[i][j] = av_clip((delta_chroma_offset_l0 - ((128 * s->sh.chroma_weight_l0[i][j])
|
|
>> s->sh.chroma_log2_weight_denom) + 128), -128, 127);
|
|
}
|
|
} else {
|
|
s->sh.chroma_weight_l0[i][0] = 1 << s->sh.chroma_log2_weight_denom;
|
|
s->sh.chroma_offset_l0[i][0] = 0;
|
|
s->sh.chroma_weight_l0[i][1] = 1 << s->sh.chroma_log2_weight_denom;
|
|
s->sh.chroma_offset_l0[i][1] = 0;
|
|
}
|
|
}
|
|
if (s->sh.slice_type == HEVC_SLICE_B) {
|
|
for (i = 0; i < s->sh.nb_refs[L1]; i++) {
|
|
luma_weight_l1_flag[i] = get_bits1(gb);
|
|
if (!luma_weight_l1_flag[i]) {
|
|
s->sh.luma_weight_l1[i] = 1 << s->sh.luma_log2_weight_denom;
|
|
s->sh.luma_offset_l1[i] = 0;
|
|
}
|
|
}
|
|
if (s->ps.sps->chroma_format_idc != 0) {
|
|
for (i = 0; i < s->sh.nb_refs[L1]; i++)
|
|
chroma_weight_l1_flag[i] = get_bits1(gb);
|
|
} else {
|
|
for (i = 0; i < s->sh.nb_refs[L1]; i++)
|
|
chroma_weight_l1_flag[i] = 0;
|
|
}
|
|
for (i = 0; i < s->sh.nb_refs[L1]; i++) {
|
|
if (luma_weight_l1_flag[i]) {
|
|
int delta_luma_weight_l1 = get_se_golomb(gb);
|
|
s->sh.luma_weight_l1[i] = (1 << s->sh.luma_log2_weight_denom) + delta_luma_weight_l1;
|
|
s->sh.luma_offset_l1[i] = get_se_golomb(gb);
|
|
}
|
|
if (chroma_weight_l1_flag[i]) {
|
|
for (j = 0; j < 2; j++) {
|
|
int delta_chroma_weight_l1 = get_se_golomb(gb);
|
|
int delta_chroma_offset_l1 = get_se_golomb(gb);
|
|
s->sh.chroma_weight_l1[i][j] = (1 << s->sh.chroma_log2_weight_denom) + delta_chroma_weight_l1;
|
|
s->sh.chroma_offset_l1[i][j] = av_clip((delta_chroma_offset_l1 - ((128 * s->sh.chroma_weight_l1[i][j])
|
|
>> s->sh.chroma_log2_weight_denom) + 128), -128, 127);
|
|
}
|
|
} else {
|
|
s->sh.chroma_weight_l1[i][0] = 1 << s->sh.chroma_log2_weight_denom;
|
|
s->sh.chroma_offset_l1[i][0] = 0;
|
|
s->sh.chroma_weight_l1[i][1] = 1 << s->sh.chroma_log2_weight_denom;
|
|
s->sh.chroma_offset_l1[i][1] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb)
|
|
{
|
|
const HEVCSPS *sps = s->ps.sps;
|
|
int max_poc_lsb = 1 << sps->log2_max_poc_lsb;
|
|
int prev_delta_msb = 0;
|
|
unsigned int nb_sps = 0, nb_sh;
|
|
int i;
|
|
|
|
rps->nb_refs = 0;
|
|
if (!sps->long_term_ref_pics_present_flag)
|
|
return 0;
|
|
|
|
if (sps->num_long_term_ref_pics_sps > 0)
|
|
nb_sps = get_ue_golomb_long(gb);
|
|
nb_sh = get_ue_golomb_long(gb);
|
|
|
|
if (nb_sh + nb_sps > FF_ARRAY_ELEMS(rps->poc))
|
|
return AVERROR_INVALIDDATA;
|
|
|
|
rps->nb_refs = nb_sh + nb_sps;
|
|
|
|
for (i = 0; i < rps->nb_refs; i++) {
|
|
uint8_t delta_poc_msb_present;
|
|
|
|
if (i < nb_sps) {
|
|
uint8_t lt_idx_sps = 0;
|
|
|
|
if (sps->num_long_term_ref_pics_sps > 1)
|
|
lt_idx_sps = get_bits(gb, av_ceil_log2(sps->num_long_term_ref_pics_sps));
|
|
|
|
rps->poc[i] = sps->lt_ref_pic_poc_lsb_sps[lt_idx_sps];
|
|
rps->used[i] = sps->used_by_curr_pic_lt_sps_flag[lt_idx_sps];
|
|
} else {
|
|
rps->poc[i] = get_bits(gb, sps->log2_max_poc_lsb);
|
|
rps->used[i] = get_bits1(gb);
|
|
}
|
|
|
|
delta_poc_msb_present = get_bits1(gb);
|
|
if (delta_poc_msb_present) {
|
|
int delta = get_ue_golomb_long(gb);
|
|
|
|
if (i && i != nb_sps)
|
|
delta += prev_delta_msb;
|
|
|
|
rps->poc[i] += s->poc - delta * max_poc_lsb - s->sh.pic_order_cnt_lsb;
|
|
prev_delta_msb = delta;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void export_stream_params(AVCodecContext *avctx, const HEVCParamSets *ps,
|
|
const HEVCSPS *sps)
|
|
{
|
|
const HEVCVPS *vps = (const HEVCVPS*)ps->vps_list[sps->vps_id]->data;
|
|
const HEVCWindow *ow = &sps->output_window;
|
|
unsigned int num = 0, den = 0;
|
|
|
|
avctx->pix_fmt = sps->pix_fmt;
|
|
avctx->coded_width = sps->width;
|
|
avctx->coded_height = sps->height;
|
|
avctx->width = sps->width - ow->left_offset - ow->right_offset;
|
|
avctx->height = sps->height - ow->top_offset - ow->bottom_offset;
|
|
avctx->has_b_frames = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics;
|
|
avctx->profile = sps->ptl.general_ptl.profile_idc;
|
|
avctx->level = sps->ptl.general_ptl.level_idc;
|
|
|
|
ff_set_sar(avctx, sps->vui.sar);
|
|
|
|
if (sps->vui.video_signal_type_present_flag)
|
|
avctx->color_range = sps->vui.video_full_range_flag ? AVCOL_RANGE_JPEG
|
|
: AVCOL_RANGE_MPEG;
|
|
else
|
|
avctx->color_range = AVCOL_RANGE_MPEG;
|
|
|
|
if (sps->vui.colour_description_present_flag) {
|
|
avctx->color_primaries = sps->vui.colour_primaries;
|
|
avctx->color_trc = sps->vui.transfer_characteristic;
|
|
avctx->colorspace = sps->vui.matrix_coeffs;
|
|
} else {
|
|
avctx->color_primaries = AVCOL_PRI_UNSPECIFIED;
|
|
avctx->color_trc = AVCOL_TRC_UNSPECIFIED;
|
|
avctx->colorspace = AVCOL_SPC_UNSPECIFIED;
|
|
}
|
|
|
|
if (vps->vps_timing_info_present_flag) {
|
|
num = vps->vps_num_units_in_tick;
|
|
den = vps->vps_time_scale;
|
|
} else if (sps->vui.vui_timing_info_present_flag) {
|
|
num = sps->vui.vui_num_units_in_tick;
|
|
den = sps->vui.vui_time_scale;
|
|
}
|
|
|
|
if (num != 0 && den != 0)
|
|
av_reduce(&avctx->framerate.den, &avctx->framerate.num,
|
|
num, den, 1 << 30);
|
|
}
|
|
|
|
static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
|
|
{
|
|
#define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \
|
|
CONFIG_HEVC_VAAPI_HWACCEL + CONFIG_HEVC_VDPAU_HWACCEL)
|
|
enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts;
|
|
|
|
if (sps->pix_fmt == AV_PIX_FMT_YUV420P || sps->pix_fmt == AV_PIX_FMT_YUVJ420P ||
|
|
sps->pix_fmt == AV_PIX_FMT_YUV420P10) {
|
|
#if CONFIG_HEVC_D3D11VA_HWACCEL
|
|
*fmt++ = AV_PIX_FMT_D3D11VA_VLD;
|
|
*fmt++ = AV_PIX_FMT_D3D11;
|
|
#endif
|
|
#if CONFIG_HEVC_DXVA2_HWACCEL
|
|
*fmt++ = AV_PIX_FMT_DXVA2_VLD;
|
|
#endif
|
|
#if CONFIG_HEVC_VAAPI_HWACCEL
|
|
*fmt++ = AV_PIX_FMT_VAAPI;
|
|
#endif
|
|
}
|
|
if (sps->pix_fmt == AV_PIX_FMT_YUV420P || sps->pix_fmt == AV_PIX_FMT_YUVJ420P) {
|
|
#if CONFIG_HEVC_VDPAU_HWACCEL
|
|
*fmt++ = AV_PIX_FMT_VDPAU;
|
|
#endif
|
|
}
|
|
|
|
*fmt++ = sps->pix_fmt;
|
|
*fmt = AV_PIX_FMT_NONE;
|
|
|
|
return ff_get_format(s->avctx, pix_fmts);
|
|
}
|
|
|
|
static int set_sps(HEVCContext *s, const HEVCSPS *sps,
|
|
enum AVPixelFormat pix_fmt)
|
|
{
|
|
int ret;
|
|
|
|
pic_arrays_free(s);
|
|
s->ps.sps = NULL;
|
|
s->ps.vps = NULL;
|
|
|
|
if (!sps)
|
|
return 0;
|
|
|
|
ret = pic_arrays_init(s, sps);
|
|
if (ret < 0)
|
|
goto fail;
|
|
|
|
export_stream_params(s->avctx, &s->ps, sps);
|
|
|
|
s->avctx->pix_fmt = pix_fmt;
|
|
|
|
ff_hevc_pred_init(&s->hpc, sps->bit_depth);
|
|
ff_hevc_dsp_init (&s->hevcdsp, sps->bit_depth);
|
|
ff_videodsp_init (&s->vdsp, sps->bit_depth);
|
|
|
|
if (sps->sao_enabled && !s->avctx->hwaccel) {
|
|
av_frame_unref(s->tmp_frame);
|
|
ret = ff_get_buffer(s->avctx, s->tmp_frame, AV_GET_BUFFER_FLAG_REF);
|
|
if (ret < 0)
|
|
goto fail;
|
|
s->frame = s->tmp_frame;
|
|
}
|
|
|
|
s->ps.sps = sps;
|
|
s->ps.vps = (HEVCVPS*) s->ps.vps_list[s->ps.sps->vps_id]->data;
|
|
|
|
return 0;
|
|
|
|
fail:
|
|
pic_arrays_free(s);
|
|
s->ps.sps = NULL;
|
|
return ret;
|
|
}
|
|
|
|
static int hls_slice_header(HEVCContext *s)
|
|
{
|
|
GetBitContext *gb = &s->HEVClc.gb;
|
|
SliceHeader *sh = &s->sh;
|
|
int i, ret;
|
|
|
|
// Coded parameters
|
|
sh->first_slice_in_pic_flag = get_bits1(gb);
|
|
if ((IS_IDR(s) || IS_BLA(s)) && sh->first_slice_in_pic_flag) {
|
|
s->seq_decode = (s->seq_decode + 1) & 0xff;
|
|
s->max_ra = INT_MAX;
|
|
if (IS_IDR(s))
|
|
ff_hevc_clear_refs(s);
|
|
}
|
|
if (IS_IRAP(s))
|
|
sh->no_output_of_prior_pics_flag = get_bits1(gb);
|
|
|
|
sh->pps_id = get_ue_golomb_long(gb);
|
|
if (sh->pps_id >= HEVC_MAX_PPS_COUNT || !s->ps.pps_list[sh->pps_id]) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
if (!sh->first_slice_in_pic_flag &&
|
|
s->ps.pps != (HEVCPPS*)s->ps.pps_list[sh->pps_id]->data) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "PPS changed between slices.\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
s->ps.pps = (HEVCPPS*)s->ps.pps_list[sh->pps_id]->data;
|
|
|
|
if (s->ps.sps != (HEVCSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data) {
|
|
const HEVCSPS *sps = (HEVCSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data;
|
|
enum AVPixelFormat pix_fmt;
|
|
|
|
ff_hevc_clear_refs(s);
|
|
|
|
pix_fmt = get_format(s, sps);
|
|
if (pix_fmt < 0)
|
|
return pix_fmt;
|
|
|
|
ret = set_sps(s, sps, pix_fmt);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
s->seq_decode = (s->seq_decode + 1) & 0xff;
|
|
s->max_ra = INT_MAX;
|
|
}
|
|
|
|
sh->dependent_slice_segment_flag = 0;
|
|
if (!sh->first_slice_in_pic_flag) {
|
|
int slice_address_length;
|
|
|
|
if (s->ps.pps->dependent_slice_segments_enabled_flag)
|
|
sh->dependent_slice_segment_flag = get_bits1(gb);
|
|
|
|
slice_address_length = av_ceil_log2(s->ps.sps->ctb_width *
|
|
s->ps.sps->ctb_height);
|
|
sh->slice_segment_addr = slice_address_length ? get_bits(gb, slice_address_length) : 0;
|
|
if (sh->slice_segment_addr >= s->ps.sps->ctb_width * s->ps.sps->ctb_height) {
|
|
av_log(s->avctx, AV_LOG_ERROR,
|
|
"Invalid slice segment address: %u.\n",
|
|
sh->slice_segment_addr);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
if (!sh->dependent_slice_segment_flag) {
|
|
sh->slice_addr = sh->slice_segment_addr;
|
|
s->slice_idx++;
|
|
}
|
|
} else {
|
|
sh->slice_segment_addr = sh->slice_addr = 0;
|
|
s->slice_idx = 0;
|
|
s->slice_initialized = 0;
|
|
}
|
|
|
|
if (!sh->dependent_slice_segment_flag) {
|
|
s->slice_initialized = 0;
|
|
|
|
for (i = 0; i < s->ps.pps->num_extra_slice_header_bits; i++)
|
|
skip_bits(gb, 1); // slice_reserved_undetermined_flag[]
|
|
|
|
sh->slice_type = get_ue_golomb_long(gb);
|
|
if (!(sh->slice_type == HEVC_SLICE_I ||
|
|
sh->slice_type == HEVC_SLICE_P ||
|
|
sh->slice_type == HEVC_SLICE_B)) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n",
|
|
sh->slice_type);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
if (IS_IRAP(s) && sh->slice_type != HEVC_SLICE_I) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "Inter slices in an IRAP frame.\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
// when flag is not present, picture is inferred to be output
|
|
sh->pic_output_flag = 1;
|
|
if (s->ps.pps->output_flag_present_flag)
|
|
sh->pic_output_flag = get_bits1(gb);
|
|
|
|
if (s->ps.sps->separate_colour_plane_flag)
|
|
sh->colour_plane_id = get_bits(gb, 2);
|
|
|
|
if (!IS_IDR(s)) {
|
|
int poc, pos;
|
|
|
|
sh->pic_order_cnt_lsb = get_bits(gb, s->ps.sps->log2_max_poc_lsb);
|
|
poc = ff_hevc_compute_poc(s, sh->pic_order_cnt_lsb);
|
|
if (!sh->first_slice_in_pic_flag && poc != s->poc) {
|
|
av_log(s->avctx, AV_LOG_WARNING,
|
|
"Ignoring POC change between slices: %d -> %d\n", s->poc, poc);
|
|
if (s->avctx->err_recognition & AV_EF_EXPLODE)
|
|
return AVERROR_INVALIDDATA;
|
|
poc = s->poc;
|
|
}
|
|
s->poc = poc;
|
|
|
|
sh->short_term_ref_pic_set_sps_flag = get_bits1(gb);
|
|
pos = get_bits_left(gb);
|
|
if (!sh->short_term_ref_pic_set_sps_flag) {
|
|
ret = ff_hevc_decode_short_term_rps(gb, s->avctx, &sh->slice_rps, s->ps.sps, 1);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
sh->short_term_rps = &sh->slice_rps;
|
|
} else {
|
|
int numbits, rps_idx;
|
|
|
|
if (!s->ps.sps->nb_st_rps) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "No ref lists in the SPS.\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
numbits = av_ceil_log2(s->ps.sps->nb_st_rps);
|
|
rps_idx = numbits > 0 ? get_bits(gb, numbits) : 0;
|
|
sh->short_term_rps = &s->ps.sps->st_rps[rps_idx];
|
|
}
|
|
sh->short_term_ref_pic_set_size = pos - get_bits_left(gb);
|
|
|
|
pos = get_bits_left(gb);
|
|
ret = decode_lt_rps(s, &sh->long_term_rps, gb);
|
|
if (ret < 0) {
|
|
av_log(s->avctx, AV_LOG_WARNING, "Invalid long term RPS.\n");
|
|
if (s->avctx->err_recognition & AV_EF_EXPLODE)
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
sh->long_term_ref_pic_set_size = pos - get_bits_left(gb);
|
|
|
|
if (s->ps.sps->sps_temporal_mvp_enabled_flag)
|
|
sh->slice_temporal_mvp_enabled_flag = get_bits1(gb);
|
|
else
|
|
sh->slice_temporal_mvp_enabled_flag = 0;
|
|
} else {
|
|
s->sh.short_term_rps = NULL;
|
|
s->poc = 0;
|
|
}
|
|
|
|
/* 8.3.1 */
|
|
if (s->temporal_id == 0 &&
|
|
s->nal_unit_type != HEVC_NAL_TRAIL_N &&
|
|
s->nal_unit_type != HEVC_NAL_TSA_N &&
|
|
s->nal_unit_type != HEVC_NAL_STSA_N &&
|
|
s->nal_unit_type != HEVC_NAL_RADL_N &&
|
|
s->nal_unit_type != HEVC_NAL_RADL_R &&
|
|
s->nal_unit_type != HEVC_NAL_RASL_N &&
|
|
s->nal_unit_type != HEVC_NAL_RASL_R)
|
|
s->pocTid0 = s->poc;
|
|
|
|
if (s->ps.sps->sao_enabled) {
|
|
sh->slice_sample_adaptive_offset_flag[0] = get_bits1(gb);
|
|
sh->slice_sample_adaptive_offset_flag[1] =
|
|
sh->slice_sample_adaptive_offset_flag[2] = get_bits1(gb);
|
|
} else {
|
|
sh->slice_sample_adaptive_offset_flag[0] = 0;
|
|
sh->slice_sample_adaptive_offset_flag[1] = 0;
|
|
sh->slice_sample_adaptive_offset_flag[2] = 0;
|
|
}
|
|
|
|
sh->nb_refs[L0] = sh->nb_refs[L1] = 0;
|
|
if (sh->slice_type == HEVC_SLICE_P || sh->slice_type == HEVC_SLICE_B) {
|
|
int nb_refs;
|
|
|
|
sh->nb_refs[L0] = s->ps.pps->num_ref_idx_l0_default_active;
|
|
if (sh->slice_type == HEVC_SLICE_B)
|
|
sh->nb_refs[L1] = s->ps.pps->num_ref_idx_l1_default_active;
|
|
|
|
if (get_bits1(gb)) { // num_ref_idx_active_override_flag
|
|
sh->nb_refs[L0] = get_ue_golomb_long(gb) + 1;
|
|
if (sh->slice_type == HEVC_SLICE_B)
|
|
sh->nb_refs[L1] = get_ue_golomb_long(gb) + 1;
|
|
}
|
|
if (sh->nb_refs[L0] > HEVC_MAX_REFS || sh->nb_refs[L1] > HEVC_MAX_REFS) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "Too many refs: %d/%d.\n",
|
|
sh->nb_refs[L0], sh->nb_refs[L1]);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
sh->rpl_modification_flag[0] = 0;
|
|
sh->rpl_modification_flag[1] = 0;
|
|
nb_refs = ff_hevc_frame_nb_refs(s);
|
|
if (!nb_refs) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "Zero refs for a frame with P or B slices.\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
if (s->ps.pps->lists_modification_present_flag && nb_refs > 1) {
|
|
sh->rpl_modification_flag[0] = get_bits1(gb);
|
|
if (sh->rpl_modification_flag[0]) {
|
|
for (i = 0; i < sh->nb_refs[L0]; i++)
|
|
sh->list_entry_lx[0][i] = get_bits(gb, av_ceil_log2(nb_refs));
|
|
}
|
|
|
|
if (sh->slice_type == HEVC_SLICE_B) {
|
|
sh->rpl_modification_flag[1] = get_bits1(gb);
|
|
if (sh->rpl_modification_flag[1] == 1)
|
|
for (i = 0; i < sh->nb_refs[L1]; i++)
|
|
sh->list_entry_lx[1][i] = get_bits(gb, av_ceil_log2(nb_refs));
|
|
}
|
|
}
|
|
|
|
if (sh->slice_type == HEVC_SLICE_B)
|
|
sh->mvd_l1_zero_flag = get_bits1(gb);
|
|
|
|
if (s->ps.pps->cabac_init_present_flag)
|
|
sh->cabac_init_flag = get_bits1(gb);
|
|
else
|
|
sh->cabac_init_flag = 0;
|
|
|
|
sh->collocated_ref_idx = 0;
|
|
if (sh->slice_temporal_mvp_enabled_flag) {
|
|
sh->collocated_list = L0;
|
|
if (sh->slice_type == HEVC_SLICE_B)
|
|
sh->collocated_list = !get_bits1(gb);
|
|
|
|
if (sh->nb_refs[sh->collocated_list] > 1) {
|
|
sh->collocated_ref_idx = get_ue_golomb_long(gb);
|
|
if (sh->collocated_ref_idx >= sh->nb_refs[sh->collocated_list]) {
|
|
av_log(s->avctx, AV_LOG_ERROR,
|
|
"Invalid collocated_ref_idx: %d.\n",
|
|
sh->collocated_ref_idx);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((s->ps.pps->weighted_pred_flag && sh->slice_type == HEVC_SLICE_P) ||
|
|
(s->ps.pps->weighted_bipred_flag && sh->slice_type == HEVC_SLICE_B)) {
|
|
pred_weight_table(s, gb);
|
|
}
|
|
|
|
sh->max_num_merge_cand = 5 - get_ue_golomb_long(gb);
|
|
if (sh->max_num_merge_cand < 1 || sh->max_num_merge_cand > 5) {
|
|
av_log(s->avctx, AV_LOG_ERROR,
|
|
"Invalid number of merging MVP candidates: %d.\n",
|
|
sh->max_num_merge_cand);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
}
|
|
|
|
sh->slice_qp_delta = get_se_golomb(gb);
|
|
|
|
if (s->ps.pps->pic_slice_level_chroma_qp_offsets_present_flag) {
|
|
sh->slice_cb_qp_offset = get_se_golomb(gb);
|
|
sh->slice_cr_qp_offset = get_se_golomb(gb);
|
|
} else {
|
|
sh->slice_cb_qp_offset = 0;
|
|
sh->slice_cr_qp_offset = 0;
|
|
}
|
|
|
|
if (s->ps.pps->deblocking_filter_control_present_flag) {
|
|
int deblocking_filter_override_flag = 0;
|
|
|
|
if (s->ps.pps->deblocking_filter_override_enabled_flag)
|
|
deblocking_filter_override_flag = get_bits1(gb);
|
|
|
|
if (deblocking_filter_override_flag) {
|
|
sh->disable_deblocking_filter_flag = get_bits1(gb);
|
|
if (!sh->disable_deblocking_filter_flag) {
|
|
sh->beta_offset = get_se_golomb(gb) * 2;
|
|
sh->tc_offset = get_se_golomb(gb) * 2;
|
|
}
|
|
} else {
|
|
sh->disable_deblocking_filter_flag = s->ps.pps->disable_dbf;
|
|
sh->beta_offset = s->ps.pps->beta_offset;
|
|
sh->tc_offset = s->ps.pps->tc_offset;
|
|
}
|
|
} else {
|
|
sh->disable_deblocking_filter_flag = 0;
|
|
sh->beta_offset = 0;
|
|
sh->tc_offset = 0;
|
|
}
|
|
|
|
if (s->ps.pps->seq_loop_filter_across_slices_enabled_flag &&
|
|
(sh->slice_sample_adaptive_offset_flag[0] ||
|
|
sh->slice_sample_adaptive_offset_flag[1] ||
|
|
!sh->disable_deblocking_filter_flag)) {
|
|
sh->slice_loop_filter_across_slices_enabled_flag = get_bits1(gb);
|
|
} else {
|
|
sh->slice_loop_filter_across_slices_enabled_flag = s->ps.pps->seq_loop_filter_across_slices_enabled_flag;
|
|
}
|
|
} else if (!s->slice_initialized) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "Independent slice segment missing.\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
sh->num_entry_point_offsets = 0;
|
|
if (s->ps.pps->tiles_enabled_flag || s->ps.pps->entropy_coding_sync_enabled_flag) {
|
|
sh->num_entry_point_offsets = get_ue_golomb_long(gb);
|
|
if (sh->num_entry_point_offsets > 0) {
|
|
int offset_len = get_ue_golomb_long(gb) + 1;
|
|
|
|
for (i = 0; i < sh->num_entry_point_offsets; i++)
|
|
skip_bits(gb, offset_len);
|
|
}
|
|
}
|
|
|
|
if (s->ps.pps->slice_header_extension_present_flag) {
|
|
unsigned int length = get_ue_golomb_long(gb);
|
|
for (i = 0; i < length; i++)
|
|
skip_bits(gb, 8); // slice_header_extension_data_byte
|
|
}
|
|
|
|
// Inferred parameters
|
|
sh->slice_qp = 26 + s->ps.pps->pic_init_qp_minus26 + sh->slice_qp_delta;
|
|
if (sh->slice_qp > 51 ||
|
|
sh->slice_qp < -s->ps.sps->qp_bd_offset) {
|
|
av_log(s->avctx, AV_LOG_ERROR,
|
|
"The slice_qp %d is outside the valid range "
|
|
"[%d, 51].\n",
|
|
sh->slice_qp,
|
|
-s->ps.sps->qp_bd_offset);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
sh->slice_ctb_addr_rs = sh->slice_segment_addr;
|
|
|
|
if (!s->sh.slice_ctb_addr_rs && s->sh.dependent_slice_segment_flag) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "Impossible slice segment.\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
s->HEVClc.first_qp_group = !s->sh.dependent_slice_segment_flag;
|
|
|
|
if (!s->ps.pps->cu_qp_delta_enabled_flag)
|
|
s->HEVClc.qp_y = FFUMOD(s->sh.slice_qp + 52 + 2 * s->ps.sps->qp_bd_offset,
|
|
52 + s->ps.sps->qp_bd_offset) - s->ps.sps->qp_bd_offset;
|
|
|
|
s->slice_initialized = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define CTB(tab, x, y) ((tab)[(y) * s->ps.sps->ctb_width + (x)])
|
|
|
|
#define SET_SAO(elem, value) \
|
|
do { \
|
|
if (!sao_merge_up_flag && !sao_merge_left_flag) \
|
|
sao->elem = value; \
|
|
else if (sao_merge_left_flag) \
|
|
sao->elem = CTB(s->sao, rx-1, ry).elem; \
|
|
else if (sao_merge_up_flag) \
|
|
sao->elem = CTB(s->sao, rx, ry-1).elem; \
|
|
else \
|
|
sao->elem = 0; \
|
|
} while (0)
|
|
|
|
static void hls_sao_param(HEVCContext *s, int rx, int ry)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
int sao_merge_left_flag = 0;
|
|
int sao_merge_up_flag = 0;
|
|
int shift = s->ps.sps->bit_depth - FFMIN(s->ps.sps->bit_depth, 10);
|
|
SAOParams *sao = &CTB(s->sao, rx, ry);
|
|
int c_idx, i;
|
|
|
|
if (s->sh.slice_sample_adaptive_offset_flag[0] ||
|
|
s->sh.slice_sample_adaptive_offset_flag[1]) {
|
|
if (rx > 0) {
|
|
if (lc->ctb_left_flag)
|
|
sao_merge_left_flag = ff_hevc_sao_merge_flag_decode(s);
|
|
}
|
|
if (ry > 0 && !sao_merge_left_flag) {
|
|
if (lc->ctb_up_flag)
|
|
sao_merge_up_flag = ff_hevc_sao_merge_flag_decode(s);
|
|
}
|
|
}
|
|
|
|
for (c_idx = 0; c_idx < 3; c_idx++) {
|
|
if (!s->sh.slice_sample_adaptive_offset_flag[c_idx]) {
|
|
sao->type_idx[c_idx] = SAO_NOT_APPLIED;
|
|
continue;
|
|
}
|
|
|
|
if (c_idx == 2) {
|
|
sao->type_idx[2] = sao->type_idx[1];
|
|
sao->eo_class[2] = sao->eo_class[1];
|
|
} else {
|
|
SET_SAO(type_idx[c_idx], ff_hevc_sao_type_idx_decode(s));
|
|
}
|
|
|
|
if (sao->type_idx[c_idx] == SAO_NOT_APPLIED)
|
|
continue;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
SET_SAO(offset_abs[c_idx][i], ff_hevc_sao_offset_abs_decode(s));
|
|
|
|
if (sao->type_idx[c_idx] == SAO_BAND) {
|
|
for (i = 0; i < 4; i++) {
|
|
if (sao->offset_abs[c_idx][i]) {
|
|
SET_SAO(offset_sign[c_idx][i],
|
|
ff_hevc_sao_offset_sign_decode(s));
|
|
} else {
|
|
sao->offset_sign[c_idx][i] = 0;
|
|
}
|
|
}
|
|
SET_SAO(band_position[c_idx], ff_hevc_sao_band_position_decode(s));
|
|
} else if (c_idx != 2) {
|
|
SET_SAO(eo_class[c_idx], ff_hevc_sao_eo_class_decode(s));
|
|
}
|
|
|
|
// Inferred parameters
|
|
sao->offset_val[c_idx][0] = 0;
|
|
for (i = 0; i < 4; i++) {
|
|
sao->offset_val[c_idx][i + 1] = sao->offset_abs[c_idx][i] << shift;
|
|
if (sao->type_idx[c_idx] == SAO_EDGE) {
|
|
if (i > 1)
|
|
sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1];
|
|
} else if (sao->offset_sign[c_idx][i]) {
|
|
sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef SET_SAO
|
|
#undef CTB
|
|
|
|
static void hls_residual_coding(HEVCContext *s, int x0, int y0,
|
|
int log2_trafo_size, enum ScanType scan_idx,
|
|
int c_idx)
|
|
{
|
|
#define GET_COORD(offset, n) \
|
|
do { \
|
|
x_c = (scan_x_cg[offset >> 4] << 2) + scan_x_off[n]; \
|
|
y_c = (scan_y_cg[offset >> 4] << 2) + scan_y_off[n]; \
|
|
} while (0)
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
int transform_skip_flag = 0;
|
|
|
|
int last_significant_coeff_x, last_significant_coeff_y;
|
|
int last_scan_pos;
|
|
int n_end;
|
|
int num_coeff = 0;
|
|
int greater1_ctx = 1;
|
|
|
|
int num_last_subset;
|
|
int x_cg_last_sig, y_cg_last_sig;
|
|
|
|
const uint8_t *scan_x_cg, *scan_y_cg, *scan_x_off, *scan_y_off;
|
|
|
|
ptrdiff_t stride = s->frame->linesize[c_idx];
|
|
int hshift = s->ps.sps->hshift[c_idx];
|
|
int vshift = s->ps.sps->vshift[c_idx];
|
|
uint8_t *dst = &s->frame->data[c_idx][(y0 >> vshift) * stride +
|
|
((x0 >> hshift) << s->ps.sps->pixel_shift)];
|
|
LOCAL_ALIGNED_32(int16_t, coeffs, [MAX_TB_SIZE * MAX_TB_SIZE]);
|
|
LOCAL_ALIGNED_8(uint8_t, significant_coeff_group_flag, [8], [8]);
|
|
|
|
int trafo_size = 1 << log2_trafo_size;
|
|
int i, qp, shift, add, scale, scale_m;
|
|
static const uint8_t level_scale[] = { 40, 45, 51, 57, 64, 72 };
|
|
const uint8_t *scale_matrix;
|
|
uint8_t dc_scale;
|
|
|
|
memset(coeffs, 0, sizeof(int16_t) * MAX_TB_SIZE * MAX_TB_SIZE);
|
|
memset(significant_coeff_group_flag, 0, sizeof(uint8_t) * 8 * 8);
|
|
// Derive QP for dequant
|
|
if (!lc->cu.cu_transquant_bypass_flag) {
|
|
static const int qp_c[] = {
|
|
29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37
|
|
};
|
|
|
|
static const uint8_t rem6[51 + 2 * 6 + 1] = {
|
|
0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2,
|
|
3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,
|
|
0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3,
|
|
};
|
|
|
|
static const uint8_t div6[51 + 2 * 6 + 1] = {
|
|
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3,
|
|
3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
|
|
7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10,
|
|
};
|
|
int qp_y = lc->qp_y;
|
|
|
|
if (c_idx == 0) {
|
|
qp = qp_y + s->ps.sps->qp_bd_offset;
|
|
} else {
|
|
int qp_i, offset;
|
|
|
|
if (c_idx == 1)
|
|
offset = s->ps.pps->cb_qp_offset + s->sh.slice_cb_qp_offset;
|
|
else
|
|
offset = s->ps.pps->cr_qp_offset + s->sh.slice_cr_qp_offset;
|
|
|
|
qp_i = av_clip(qp_y + offset, -s->ps.sps->qp_bd_offset, 57);
|
|
if (qp_i < 30)
|
|
qp = qp_i;
|
|
else if (qp_i > 43)
|
|
qp = qp_i - 6;
|
|
else
|
|
qp = qp_c[qp_i - 30];
|
|
|
|
qp += s->ps.sps->qp_bd_offset;
|
|
}
|
|
|
|
shift = s->ps.sps->bit_depth + log2_trafo_size - 5;
|
|
add = 1 << (shift - 1);
|
|
scale = level_scale[rem6[qp]] << (div6[qp]);
|
|
scale_m = 16; // default when no custom scaling lists.
|
|
dc_scale = 16;
|
|
|
|
if (s->ps.sps->scaling_list_enable_flag) {
|
|
const ScalingList *sl = s->ps.pps->scaling_list_data_present_flag ?
|
|
&s->ps.pps->scaling_list : &s->ps.sps->scaling_list;
|
|
int matrix_id = lc->cu.pred_mode != MODE_INTRA;
|
|
|
|
if (log2_trafo_size != 5)
|
|
matrix_id = 3 * matrix_id + c_idx;
|
|
|
|
scale_matrix = sl->sl[log2_trafo_size - 2][matrix_id];
|
|
if (log2_trafo_size >= 4)
|
|
dc_scale = sl->sl_dc[log2_trafo_size - 4][matrix_id];
|
|
}
|
|
}
|
|
|
|
if (s->ps.pps->transform_skip_enabled_flag &&
|
|
!lc->cu.cu_transquant_bypass_flag &&
|
|
log2_trafo_size == 2) {
|
|
transform_skip_flag = ff_hevc_transform_skip_flag_decode(s, c_idx);
|
|
}
|
|
|
|
last_significant_coeff_x =
|
|
ff_hevc_last_significant_coeff_x_prefix_decode(s, c_idx, log2_trafo_size);
|
|
last_significant_coeff_y =
|
|
ff_hevc_last_significant_coeff_y_prefix_decode(s, c_idx, log2_trafo_size);
|
|
|
|
if (last_significant_coeff_x > 3) {
|
|
int suffix = ff_hevc_last_significant_coeff_suffix_decode(s, last_significant_coeff_x);
|
|
last_significant_coeff_x = (1 << ((last_significant_coeff_x >> 1) - 1)) *
|
|
(2 + (last_significant_coeff_x & 1)) +
|
|
suffix;
|
|
}
|
|
|
|
if (last_significant_coeff_y > 3) {
|
|
int suffix = ff_hevc_last_significant_coeff_suffix_decode(s, last_significant_coeff_y);
|
|
last_significant_coeff_y = (1 << ((last_significant_coeff_y >> 1) - 1)) *
|
|
(2 + (last_significant_coeff_y & 1)) +
|
|
suffix;
|
|
}
|
|
|
|
if (scan_idx == SCAN_VERT)
|
|
FFSWAP(int, last_significant_coeff_x, last_significant_coeff_y);
|
|
|
|
x_cg_last_sig = last_significant_coeff_x >> 2;
|
|
y_cg_last_sig = last_significant_coeff_y >> 2;
|
|
|
|
switch (scan_idx) {
|
|
case SCAN_DIAG: {
|
|
int last_x_c = last_significant_coeff_x & 3;
|
|
int last_y_c = last_significant_coeff_y & 3;
|
|
|
|
scan_x_off = ff_hevc_diag_scan4x4_x;
|
|
scan_y_off = ff_hevc_diag_scan4x4_y;
|
|
num_coeff = diag_scan4x4_inv[last_y_c][last_x_c];
|
|
if (trafo_size == 4) {
|
|
scan_x_cg = scan_1x1;
|
|
scan_y_cg = scan_1x1;
|
|
} else if (trafo_size == 8) {
|
|
num_coeff += diag_scan2x2_inv[y_cg_last_sig][x_cg_last_sig] << 4;
|
|
scan_x_cg = diag_scan2x2_x;
|
|
scan_y_cg = diag_scan2x2_y;
|
|
} else if (trafo_size == 16) {
|
|
num_coeff += diag_scan4x4_inv[y_cg_last_sig][x_cg_last_sig] << 4;
|
|
scan_x_cg = ff_hevc_diag_scan4x4_x;
|
|
scan_y_cg = ff_hevc_diag_scan4x4_y;
|
|
} else { // trafo_size == 32
|
|
num_coeff += diag_scan8x8_inv[y_cg_last_sig][x_cg_last_sig] << 4;
|
|
scan_x_cg = ff_hevc_diag_scan8x8_x;
|
|
scan_y_cg = ff_hevc_diag_scan8x8_y;
|
|
}
|
|
break;
|
|
}
|
|
case SCAN_HORIZ:
|
|
scan_x_cg = horiz_scan2x2_x;
|
|
scan_y_cg = horiz_scan2x2_y;
|
|
scan_x_off = horiz_scan4x4_x;
|
|
scan_y_off = horiz_scan4x4_y;
|
|
num_coeff = horiz_scan8x8_inv[last_significant_coeff_y][last_significant_coeff_x];
|
|
break;
|
|
default: //SCAN_VERT
|
|
scan_x_cg = horiz_scan2x2_y;
|
|
scan_y_cg = horiz_scan2x2_x;
|
|
scan_x_off = horiz_scan4x4_y;
|
|
scan_y_off = horiz_scan4x4_x;
|
|
num_coeff = horiz_scan8x8_inv[last_significant_coeff_x][last_significant_coeff_y];
|
|
break;
|
|
}
|
|
num_coeff++;
|
|
num_last_subset = (num_coeff - 1) >> 4;
|
|
|
|
for (i = num_last_subset; i >= 0; i--) {
|
|
int n, m;
|
|
int x_cg, y_cg, x_c, y_c;
|
|
int implicit_non_zero_coeff = 0;
|
|
int64_t trans_coeff_level;
|
|
int prev_sig = 0;
|
|
int offset = i << 4;
|
|
|
|
uint8_t significant_coeff_flag_idx[16];
|
|
uint8_t nb_significant_coeff_flag = 0;
|
|
|
|
x_cg = scan_x_cg[i];
|
|
y_cg = scan_y_cg[i];
|
|
|
|
if (i < num_last_subset && i > 0) {
|
|
int ctx_cg = 0;
|
|
if (x_cg < (1 << (log2_trafo_size - 2)) - 1)
|
|
ctx_cg += significant_coeff_group_flag[x_cg + 1][y_cg];
|
|
if (y_cg < (1 << (log2_trafo_size - 2)) - 1)
|
|
ctx_cg += significant_coeff_group_flag[x_cg][y_cg + 1];
|
|
|
|
significant_coeff_group_flag[x_cg][y_cg] =
|
|
ff_hevc_significant_coeff_group_flag_decode(s, c_idx, ctx_cg);
|
|
implicit_non_zero_coeff = 1;
|
|
} else {
|
|
significant_coeff_group_flag[x_cg][y_cg] =
|
|
((x_cg == x_cg_last_sig && y_cg == y_cg_last_sig) ||
|
|
(x_cg == 0 && y_cg == 0));
|
|
}
|
|
|
|
last_scan_pos = num_coeff - offset - 1;
|
|
|
|
if (i == num_last_subset) {
|
|
n_end = last_scan_pos - 1;
|
|
significant_coeff_flag_idx[0] = last_scan_pos;
|
|
nb_significant_coeff_flag = 1;
|
|
} else {
|
|
n_end = 15;
|
|
}
|
|
|
|
if (x_cg < ((1 << log2_trafo_size) - 1) >> 2)
|
|
prev_sig = significant_coeff_group_flag[x_cg + 1][y_cg];
|
|
if (y_cg < ((1 << log2_trafo_size) - 1) >> 2)
|
|
prev_sig += significant_coeff_group_flag[x_cg][y_cg + 1] << 1;
|
|
|
|
for (n = n_end; n >= 0; n--) {
|
|
GET_COORD(offset, n);
|
|
|
|
if (significant_coeff_group_flag[x_cg][y_cg] &&
|
|
(n > 0 || implicit_non_zero_coeff == 0)) {
|
|
if (ff_hevc_significant_coeff_flag_decode(s, c_idx, x_c, y_c,
|
|
log2_trafo_size,
|
|
scan_idx,
|
|
prev_sig) == 1) {
|
|
significant_coeff_flag_idx[nb_significant_coeff_flag] = n;
|
|
nb_significant_coeff_flag++;
|
|
implicit_non_zero_coeff = 0;
|
|
}
|
|
} else {
|
|
int last_cg = (x_c == (x_cg << 2) && y_c == (y_cg << 2));
|
|
if (last_cg && implicit_non_zero_coeff && significant_coeff_group_flag[x_cg][y_cg]) {
|
|
significant_coeff_flag_idx[nb_significant_coeff_flag] = n;
|
|
nb_significant_coeff_flag++;
|
|
}
|
|
}
|
|
}
|
|
|
|
n_end = nb_significant_coeff_flag;
|
|
|
|
if (n_end) {
|
|
int first_nz_pos_in_cg = 16;
|
|
int last_nz_pos_in_cg = -1;
|
|
int c_rice_param = 0;
|
|
int first_greater1_coeff_idx = -1;
|
|
uint8_t coeff_abs_level_greater1_flag[16] = { 0 };
|
|
uint16_t coeff_sign_flag;
|
|
int sum_abs = 0;
|
|
int sign_hidden = 0;
|
|
|
|
// initialize first elem of coeff_bas_level_greater1_flag
|
|
int ctx_set = (i > 0 && c_idx == 0) ? 2 : 0;
|
|
|
|
if (!(i == num_last_subset) && greater1_ctx == 0)
|
|
ctx_set++;
|
|
greater1_ctx = 1;
|
|
last_nz_pos_in_cg = significant_coeff_flag_idx[0];
|
|
|
|
for (m = 0; m < (n_end > 8 ? 8 : n_end); m++) {
|
|
int n_idx = significant_coeff_flag_idx[m];
|
|
int inc = (ctx_set << 2) + greater1_ctx;
|
|
coeff_abs_level_greater1_flag[n_idx] =
|
|
ff_hevc_coeff_abs_level_greater1_flag_decode(s, c_idx, inc);
|
|
if (coeff_abs_level_greater1_flag[n_idx]) {
|
|
greater1_ctx = 0;
|
|
} else if (greater1_ctx > 0 && greater1_ctx < 3) {
|
|
greater1_ctx++;
|
|
}
|
|
|
|
if (coeff_abs_level_greater1_flag[n_idx] &&
|
|
first_greater1_coeff_idx == -1)
|
|
first_greater1_coeff_idx = n_idx;
|
|
}
|
|
first_nz_pos_in_cg = significant_coeff_flag_idx[n_end - 1];
|
|
sign_hidden = last_nz_pos_in_cg - first_nz_pos_in_cg >= 4 &&
|
|
!lc->cu.cu_transquant_bypass_flag;
|
|
|
|
if (first_greater1_coeff_idx != -1) {
|
|
coeff_abs_level_greater1_flag[first_greater1_coeff_idx] += ff_hevc_coeff_abs_level_greater2_flag_decode(s, c_idx, ctx_set);
|
|
}
|
|
if (!s->ps.pps->sign_data_hiding_flag || !sign_hidden) {
|
|
coeff_sign_flag = ff_hevc_coeff_sign_flag(s, nb_significant_coeff_flag) << (16 - nb_significant_coeff_flag);
|
|
} else {
|
|
coeff_sign_flag = ff_hevc_coeff_sign_flag(s, nb_significant_coeff_flag - 1) << (16 - (nb_significant_coeff_flag - 1));
|
|
}
|
|
|
|
for (m = 0; m < n_end; m++) {
|
|
n = significant_coeff_flag_idx[m];
|
|
GET_COORD(offset, n);
|
|
trans_coeff_level = 1 + coeff_abs_level_greater1_flag[n];
|
|
if (trans_coeff_level == ((m < 8) ?
|
|
((n == first_greater1_coeff_idx) ? 3 : 2) : 1)) {
|
|
trans_coeff_level += ff_hevc_coeff_abs_level_remaining(s, trans_coeff_level, c_rice_param);
|
|
if ((trans_coeff_level) > (3 * (1 << c_rice_param)))
|
|
c_rice_param = FFMIN(c_rice_param + 1, 4);
|
|
}
|
|
if (s->ps.pps->sign_data_hiding_flag && sign_hidden) {
|
|
sum_abs += trans_coeff_level;
|
|
if (n == first_nz_pos_in_cg && ((sum_abs & 1) == 1))
|
|
trans_coeff_level = -trans_coeff_level;
|
|
}
|
|
if (coeff_sign_flag >> 15)
|
|
trans_coeff_level = -trans_coeff_level;
|
|
coeff_sign_flag <<= 1;
|
|
if (!lc->cu.cu_transquant_bypass_flag) {
|
|
if (s->ps.sps->scaling_list_enable_flag) {
|
|
if (y_c || x_c || log2_trafo_size < 4) {
|
|
int pos;
|
|
switch (log2_trafo_size) {
|
|
case 3: pos = (y_c << 3) + x_c; break;
|
|
case 4: pos = ((y_c >> 1) << 3) + (x_c >> 1); break;
|
|
case 5: pos = ((y_c >> 2) << 3) + (x_c >> 2); break;
|
|
default: pos = (y_c << 2) + x_c;
|
|
}
|
|
scale_m = scale_matrix[pos];
|
|
} else {
|
|
scale_m = dc_scale;
|
|
}
|
|
}
|
|
trans_coeff_level = (trans_coeff_level * (int64_t)scale * (int64_t)scale_m + add) >> shift;
|
|
if(trans_coeff_level < 0) {
|
|
if((~trans_coeff_level) & 0xFffffffffff8000)
|
|
trans_coeff_level = -32768;
|
|
} else {
|
|
if (trans_coeff_level & 0xffffffffffff8000)
|
|
trans_coeff_level = 32767;
|
|
}
|
|
}
|
|
coeffs[y_c * trafo_size + x_c] = trans_coeff_level;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!lc->cu.cu_transquant_bypass_flag) {
|
|
if (transform_skip_flag)
|
|
s->hevcdsp.dequant(coeffs);
|
|
else if (lc->cu.pred_mode == MODE_INTRA && c_idx == 0 &&
|
|
log2_trafo_size == 2)
|
|
s->hevcdsp.transform_4x4_luma(coeffs);
|
|
else {
|
|
int max_xy = FFMAX(last_significant_coeff_x, last_significant_coeff_y);
|
|
if (max_xy == 0)
|
|
s->hevcdsp.idct_dc[log2_trafo_size - 2](coeffs);
|
|
else {
|
|
int col_limit = last_significant_coeff_x + last_significant_coeff_y + 4;
|
|
if (max_xy < 4)
|
|
col_limit = FFMIN(4, col_limit);
|
|
else if (max_xy < 8)
|
|
col_limit = FFMIN(8, col_limit);
|
|
else if (max_xy < 12)
|
|
col_limit = FFMIN(24, col_limit);
|
|
s->hevcdsp.idct[log2_trafo_size - 2](coeffs, col_limit);
|
|
}
|
|
}
|
|
}
|
|
s->hevcdsp.add_residual[log2_trafo_size - 2](dst, coeffs, stride);
|
|
}
|
|
|
|
static int hls_transform_unit(HEVCContext *s, int x0, int y0,
|
|
int xBase, int yBase, int cb_xBase, int cb_yBase,
|
|
int log2_cb_size, int log2_trafo_size,
|
|
int blk_idx, int cbf_luma, int cbf_cb, int cbf_cr)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
|
|
if (lc->cu.pred_mode == MODE_INTRA) {
|
|
int trafo_size = 1 << log2_trafo_size;
|
|
ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size);
|
|
|
|
s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, 0);
|
|
if (log2_trafo_size > 2) {
|
|
trafo_size = trafo_size << (s->ps.sps->hshift[1] - 1);
|
|
ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size);
|
|
s->hpc.intra_pred[log2_trafo_size - 3](s, x0, y0, 1);
|
|
s->hpc.intra_pred[log2_trafo_size - 3](s, x0, y0, 2);
|
|
} else if (blk_idx == 3) {
|
|
trafo_size = trafo_size << s->ps.sps->hshift[1];
|
|
ff_hevc_set_neighbour_available(s, xBase, yBase,
|
|
trafo_size, trafo_size);
|
|
s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1);
|
|
s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 2);
|
|
}
|
|
}
|
|
|
|
if (cbf_luma || cbf_cb || cbf_cr) {
|
|
int scan_idx = SCAN_DIAG;
|
|
int scan_idx_c = SCAN_DIAG;
|
|
|
|
if (s->ps.pps->cu_qp_delta_enabled_flag && !lc->tu.is_cu_qp_delta_coded) {
|
|
lc->tu.cu_qp_delta = ff_hevc_cu_qp_delta_abs(s);
|
|
if (lc->tu.cu_qp_delta != 0)
|
|
if (ff_hevc_cu_qp_delta_sign_flag(s) == 1)
|
|
lc->tu.cu_qp_delta = -lc->tu.cu_qp_delta;
|
|
lc->tu.is_cu_qp_delta_coded = 1;
|
|
|
|
if (lc->tu.cu_qp_delta < -(26 + s->ps.sps->qp_bd_offset / 2) ||
|
|
lc->tu.cu_qp_delta > (25 + s->ps.sps->qp_bd_offset / 2)) {
|
|
av_log(s->avctx, AV_LOG_ERROR,
|
|
"The cu_qp_delta %d is outside the valid range "
|
|
"[%d, %d].\n",
|
|
lc->tu.cu_qp_delta,
|
|
-(26 + s->ps.sps->qp_bd_offset / 2),
|
|
(25 + s->ps.sps->qp_bd_offset / 2));
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
ff_hevc_set_qPy(s, x0, y0, cb_xBase, cb_yBase, log2_cb_size);
|
|
}
|
|
|
|
if (lc->cu.pred_mode == MODE_INTRA && log2_trafo_size < 4) {
|
|
if (lc->tu.cur_intra_pred_mode >= 6 &&
|
|
lc->tu.cur_intra_pred_mode <= 14) {
|
|
scan_idx = SCAN_VERT;
|
|
} else if (lc->tu.cur_intra_pred_mode >= 22 &&
|
|
lc->tu.cur_intra_pred_mode <= 30) {
|
|
scan_idx = SCAN_HORIZ;
|
|
}
|
|
|
|
if (lc->pu.intra_pred_mode_c >= 6 &&
|
|
lc->pu.intra_pred_mode_c <= 14) {
|
|
scan_idx_c = SCAN_VERT;
|
|
} else if (lc->pu.intra_pred_mode_c >= 22 &&
|
|
lc->pu.intra_pred_mode_c <= 30) {
|
|
scan_idx_c = SCAN_HORIZ;
|
|
}
|
|
}
|
|
|
|
if (cbf_luma)
|
|
hls_residual_coding(s, x0, y0, log2_trafo_size, scan_idx, 0);
|
|
if (log2_trafo_size > 2) {
|
|
if (cbf_cb)
|
|
hls_residual_coding(s, x0, y0, log2_trafo_size - 1, scan_idx_c, 1);
|
|
if (cbf_cr)
|
|
hls_residual_coding(s, x0, y0, log2_trafo_size - 1, scan_idx_c, 2);
|
|
} else if (blk_idx == 3) {
|
|
if (cbf_cb)
|
|
hls_residual_coding(s, xBase, yBase, log2_trafo_size, scan_idx_c, 1);
|
|
if (cbf_cr)
|
|
hls_residual_coding(s, xBase, yBase, log2_trafo_size, scan_idx_c, 2);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void set_deblocking_bypass(HEVCContext *s, int x0, int y0, int log2_cb_size)
|
|
{
|
|
int cb_size = 1 << log2_cb_size;
|
|
int log2_min_pu_size = s->ps.sps->log2_min_pu_size;
|
|
|
|
int min_pu_width = s->ps.sps->min_pu_width;
|
|
int x_end = FFMIN(x0 + cb_size, s->ps.sps->width);
|
|
int y_end = FFMIN(y0 + cb_size, s->ps.sps->height);
|
|
int i, j;
|
|
|
|
for (j = (y0 >> log2_min_pu_size); j < (y_end >> log2_min_pu_size); j++)
|
|
for (i = (x0 >> log2_min_pu_size); i < (x_end >> log2_min_pu_size); i++)
|
|
s->is_pcm[i + j * min_pu_width] = 2;
|
|
}
|
|
|
|
static int hls_transform_tree(HEVCContext *s, int x0, int y0,
|
|
int xBase, int yBase, int cb_xBase, int cb_yBase,
|
|
int log2_cb_size, int log2_trafo_size,
|
|
int trafo_depth, int blk_idx,
|
|
int cbf_cb, int cbf_cr)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
uint8_t split_transform_flag;
|
|
int ret;
|
|
|
|
if (lc->cu.intra_split_flag) {
|
|
if (trafo_depth == 1)
|
|
lc->tu.cur_intra_pred_mode = lc->pu.intra_pred_mode[blk_idx];
|
|
} else {
|
|
lc->tu.cur_intra_pred_mode = lc->pu.intra_pred_mode[0];
|
|
}
|
|
|
|
if (log2_trafo_size <= s->ps.sps->log2_max_trafo_size &&
|
|
log2_trafo_size > s->ps.sps->log2_min_tb_size &&
|
|
trafo_depth < lc->cu.max_trafo_depth &&
|
|
!(lc->cu.intra_split_flag && trafo_depth == 0)) {
|
|
split_transform_flag = ff_hevc_split_transform_flag_decode(s, log2_trafo_size);
|
|
} else {
|
|
int inter_split = s->ps.sps->max_transform_hierarchy_depth_inter == 0 &&
|
|
lc->cu.pred_mode == MODE_INTER &&
|
|
lc->cu.part_mode != PART_2Nx2N &&
|
|
trafo_depth == 0;
|
|
|
|
split_transform_flag = log2_trafo_size > s->ps.sps->log2_max_trafo_size ||
|
|
(lc->cu.intra_split_flag && trafo_depth == 0) ||
|
|
inter_split;
|
|
}
|
|
|
|
if (log2_trafo_size > 2 && (trafo_depth == 0 || cbf_cb))
|
|
cbf_cb = ff_hevc_cbf_cb_cr_decode(s, trafo_depth);
|
|
else if (log2_trafo_size > 2 || trafo_depth == 0)
|
|
cbf_cb = 0;
|
|
if (log2_trafo_size > 2 && (trafo_depth == 0 || cbf_cr))
|
|
cbf_cr = ff_hevc_cbf_cb_cr_decode(s, trafo_depth);
|
|
else if (log2_trafo_size > 2 || trafo_depth == 0)
|
|
cbf_cr = 0;
|
|
|
|
if (split_transform_flag) {
|
|
const int trafo_size_split = 1 << (log2_trafo_size - 1);
|
|
const int x1 = x0 + trafo_size_split;
|
|
const int y1 = y0 + trafo_size_split;
|
|
|
|
#define SUBDIVIDE(x, y, idx) \
|
|
do { \
|
|
ret = hls_transform_tree(s, x, y, x0, y0, cb_xBase, cb_yBase, log2_cb_size, \
|
|
log2_trafo_size - 1, trafo_depth + 1, idx, \
|
|
cbf_cb, cbf_cr); \
|
|
if (ret < 0) \
|
|
return ret; \
|
|
} while (0)
|
|
|
|
SUBDIVIDE(x0, y0, 0);
|
|
SUBDIVIDE(x1, y0, 1);
|
|
SUBDIVIDE(x0, y1, 2);
|
|
SUBDIVIDE(x1, y1, 3);
|
|
|
|
#undef SUBDIVIDE
|
|
} else {
|
|
int min_tu_size = 1 << s->ps.sps->log2_min_tb_size;
|
|
int log2_min_tu_size = s->ps.sps->log2_min_tb_size;
|
|
int min_tu_width = s->ps.sps->min_tb_width;
|
|
int cbf_luma = 1;
|
|
|
|
if (lc->cu.pred_mode == MODE_INTRA || trafo_depth != 0 ||
|
|
cbf_cb || cbf_cr)
|
|
cbf_luma = ff_hevc_cbf_luma_decode(s, trafo_depth);
|
|
|
|
ret = hls_transform_unit(s, x0, y0, xBase, yBase, cb_xBase, cb_yBase,
|
|
log2_cb_size, log2_trafo_size,
|
|
blk_idx, cbf_luma, cbf_cb, cbf_cr);
|
|
if (ret < 0)
|
|
return ret;
|
|
// TODO: store cbf_luma somewhere else
|
|
if (cbf_luma) {
|
|
int i, j;
|
|
for (i = 0; i < (1 << log2_trafo_size); i += min_tu_size)
|
|
for (j = 0; j < (1 << log2_trafo_size); j += min_tu_size) {
|
|
int x_tu = (x0 + j) >> log2_min_tu_size;
|
|
int y_tu = (y0 + i) >> log2_min_tu_size;
|
|
s->cbf_luma[y_tu * min_tu_width + x_tu] = 1;
|
|
}
|
|
}
|
|
if (!s->sh.disable_deblocking_filter_flag) {
|
|
ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_trafo_size);
|
|
if (s->ps.pps->transquant_bypass_enable_flag &&
|
|
lc->cu.cu_transquant_bypass_flag)
|
|
set_deblocking_bypass(s, x0, y0, log2_trafo_size);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size)
|
|
{
|
|
//TODO: non-4:2:0 support
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
GetBitContext gb;
|
|
int cb_size = 1 << log2_cb_size;
|
|
ptrdiff_t stride0 = s->frame->linesize[0];
|
|
ptrdiff_t stride1 = s->frame->linesize[1];
|
|
ptrdiff_t stride2 = s->frame->linesize[2];
|
|
uint8_t *dst0 = &s->frame->data[0][y0 * stride0 + (x0 << s->ps.sps->pixel_shift)];
|
|
uint8_t *dst1 = &s->frame->data[1][(y0 >> s->ps.sps->vshift[1]) * stride1 + ((x0 >> s->ps.sps->hshift[1]) << s->ps.sps->pixel_shift)];
|
|
uint8_t *dst2 = &s->frame->data[2][(y0 >> s->ps.sps->vshift[2]) * stride2 + ((x0 >> s->ps.sps->hshift[2]) << s->ps.sps->pixel_shift)];
|
|
|
|
int length = cb_size * cb_size * s->ps.sps->pcm.bit_depth + ((cb_size * cb_size) >> 1) * s->ps.sps->pcm.bit_depth_chroma;
|
|
const uint8_t *pcm = skip_bytes(&lc->cc, (length + 7) >> 3);
|
|
int ret;
|
|
|
|
if (!s->sh.disable_deblocking_filter_flag)
|
|
ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size);
|
|
|
|
ret = init_get_bits(&gb, pcm, length);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
s->hevcdsp.put_pcm(dst0, stride0, cb_size, &gb, s->ps.sps->pcm.bit_depth);
|
|
s->hevcdsp.put_pcm(dst1, stride1, cb_size / 2, &gb, s->ps.sps->pcm.bit_depth_chroma);
|
|
s->hevcdsp.put_pcm(dst2, stride2, cb_size / 2, &gb, s->ps.sps->pcm.bit_depth_chroma);
|
|
return 0;
|
|
}
|
|
|
|
static void hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
int x = ff_hevc_abs_mvd_greater0_flag_decode(s);
|
|
int y = ff_hevc_abs_mvd_greater0_flag_decode(s);
|
|
|
|
if (x)
|
|
x += ff_hevc_abs_mvd_greater1_flag_decode(s);
|
|
if (y)
|
|
y += ff_hevc_abs_mvd_greater1_flag_decode(s);
|
|
|
|
switch (x) {
|
|
case 2: lc->pu.mvd.x = ff_hevc_mvd_decode(s); break;
|
|
case 1: lc->pu.mvd.x = ff_hevc_mvd_sign_flag_decode(s); break;
|
|
case 0: lc->pu.mvd.x = 0; break;
|
|
}
|
|
|
|
switch (y) {
|
|
case 2: lc->pu.mvd.y = ff_hevc_mvd_decode(s); break;
|
|
case 1: lc->pu.mvd.y = ff_hevc_mvd_sign_flag_decode(s); break;
|
|
case 0: lc->pu.mvd.y = 0; break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 8.5.3.2.2.1 Luma sample interpolation process
|
|
*
|
|
* @param s HEVC decoding context
|
|
* @param dst target buffer for block data at block position
|
|
* @param dststride stride of the dst buffer
|
|
* @param ref reference picture buffer at origin (0, 0)
|
|
* @param mv motion vector (relative to block position) to get pixel data from
|
|
* @param x_off horizontal position of block from origin (0, 0)
|
|
* @param y_off vertical position of block from origin (0, 0)
|
|
* @param block_w width of block
|
|
* @param block_h height of block
|
|
*/
|
|
static void luma_mc(HEVCContext *s, int16_t *dst, ptrdiff_t dststride,
|
|
AVFrame *ref, const Mv *mv, int x_off, int y_off,
|
|
int block_w, int block_h, int pred_idx)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
uint8_t *src = ref->data[0];
|
|
ptrdiff_t srcstride = ref->linesize[0];
|
|
int pic_width = s->ps.sps->width;
|
|
int pic_height = s->ps.sps->height;
|
|
|
|
int mx = mv->x & 3;
|
|
int my = mv->y & 3;
|
|
int extra_left = ff_hevc_qpel_extra_before[mx];
|
|
int extra_top = ff_hevc_qpel_extra_before[my];
|
|
|
|
x_off += mv->x >> 2;
|
|
y_off += mv->y >> 2;
|
|
src += y_off * srcstride + (x_off * (1 << s->ps.sps->pixel_shift));
|
|
|
|
if (x_off < extra_left || y_off < extra_top ||
|
|
x_off >= pic_width - block_w - ff_hevc_qpel_extra_after[mx] ||
|
|
y_off >= pic_height - block_h - ff_hevc_qpel_extra_after[my]) {
|
|
const ptrdiff_t edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift;
|
|
int offset = extra_top * srcstride + (extra_left << s->ps.sps->pixel_shift);
|
|
int buf_offset = extra_top *
|
|
edge_emu_stride + (extra_left << s->ps.sps->pixel_shift);
|
|
|
|
s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src - offset,
|
|
edge_emu_stride, srcstride,
|
|
block_w + ff_hevc_qpel_extra[mx],
|
|
block_h + ff_hevc_qpel_extra[my],
|
|
x_off - extra_left, y_off - extra_top,
|
|
pic_width, pic_height);
|
|
src = lc->edge_emu_buffer + buf_offset;
|
|
srcstride = edge_emu_stride;
|
|
}
|
|
s->hevcdsp.put_hevc_qpel[!!my][!!mx][pred_idx](dst, dststride, src, srcstride,
|
|
block_h, mx, my, lc->mc_buffer);
|
|
}
|
|
|
|
/**
|
|
* 8.5.3.2.2.2 Chroma sample interpolation process
|
|
*
|
|
* @param s HEVC decoding context
|
|
* @param dst1 target buffer for block data at block position (U plane)
|
|
* @param dst2 target buffer for block data at block position (V plane)
|
|
* @param dststride stride of the dst1 and dst2 buffers
|
|
* @param ref reference picture buffer at origin (0, 0)
|
|
* @param mv motion vector (relative to block position) to get pixel data from
|
|
* @param x_off horizontal position of block from origin (0, 0)
|
|
* @param y_off vertical position of block from origin (0, 0)
|
|
* @param block_w width of block
|
|
* @param block_h height of block
|
|
*/
|
|
static void chroma_mc(HEVCContext *s, int16_t *dst1, int16_t *dst2,
|
|
ptrdiff_t dststride, AVFrame *ref, const Mv *mv,
|
|
int x_off, int y_off, int block_w, int block_h, int pred_idx)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
uint8_t *src1 = ref->data[1];
|
|
uint8_t *src2 = ref->data[2];
|
|
ptrdiff_t src1stride = ref->linesize[1];
|
|
ptrdiff_t src2stride = ref->linesize[2];
|
|
int pic_width = s->ps.sps->width >> 1;
|
|
int pic_height = s->ps.sps->height >> 1;
|
|
|
|
int mx = mv->x & 7;
|
|
int my = mv->y & 7;
|
|
|
|
x_off += mv->x >> 3;
|
|
y_off += mv->y >> 3;
|
|
src1 += y_off * src1stride + (x_off * (1 << s->ps.sps->pixel_shift));
|
|
src2 += y_off * src2stride + (x_off * (1 << s->ps.sps->pixel_shift));
|
|
|
|
if (x_off < EPEL_EXTRA_BEFORE || y_off < EPEL_EXTRA_AFTER ||
|
|
x_off >= pic_width - block_w - EPEL_EXTRA_AFTER ||
|
|
y_off >= pic_height - block_h - EPEL_EXTRA_AFTER) {
|
|
const ptrdiff_t edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift;
|
|
int offset1 = EPEL_EXTRA_BEFORE * (src1stride + (1 << s->ps.sps->pixel_shift));
|
|
int buf_offset1 = EPEL_EXTRA_BEFORE *
|
|
(edge_emu_stride + (1 << s->ps.sps->pixel_shift));
|
|
int offset2 = EPEL_EXTRA_BEFORE * (src2stride + (1 << s->ps.sps->pixel_shift));
|
|
int buf_offset2 = EPEL_EXTRA_BEFORE *
|
|
(edge_emu_stride + (1 << s->ps.sps->pixel_shift));
|
|
|
|
s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src1 - offset1,
|
|
edge_emu_stride, src1stride,
|
|
block_w + EPEL_EXTRA, block_h + EPEL_EXTRA,
|
|
x_off - EPEL_EXTRA_BEFORE,
|
|
y_off - EPEL_EXTRA_BEFORE,
|
|
pic_width, pic_height);
|
|
|
|
src1 = lc->edge_emu_buffer + buf_offset1;
|
|
src1stride = edge_emu_stride;
|
|
s->hevcdsp.put_hevc_epel[!!my][!!mx][pred_idx](dst1, dststride, src1, src1stride,
|
|
block_h, mx, my, lc->mc_buffer);
|
|
|
|
s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src2 - offset2,
|
|
edge_emu_stride, src2stride,
|
|
block_w + EPEL_EXTRA, block_h + EPEL_EXTRA,
|
|
x_off - EPEL_EXTRA_BEFORE,
|
|
y_off - EPEL_EXTRA_BEFORE,
|
|
pic_width, pic_height);
|
|
src2 = lc->edge_emu_buffer + buf_offset2;
|
|
src2stride = edge_emu_stride;
|
|
|
|
s->hevcdsp.put_hevc_epel[!!my][!!mx][pred_idx](dst2, dststride, src2, src2stride,
|
|
block_h, mx, my, lc->mc_buffer);
|
|
} else {
|
|
s->hevcdsp.put_hevc_epel[!!my][!!mx][pred_idx](dst1, dststride, src1, src1stride,
|
|
block_h, mx, my, lc->mc_buffer);
|
|
s->hevcdsp.put_hevc_epel[!!my][!!mx][pred_idx](dst2, dststride, src2, src2stride,
|
|
block_h, mx, my, lc->mc_buffer);
|
|
}
|
|
}
|
|
|
|
static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref,
|
|
const Mv *mv, int y0, int height)
|
|
{
|
|
int y = (mv->y >> 2) + y0 + height + 9;
|
|
ff_thread_await_progress(&ref->tf, y, 0);
|
|
}
|
|
|
|
static void hevc_luma_mv_mpv_mode(HEVCContext *s, int x0, int y0, int nPbW,
|
|
int nPbH, int log2_cb_size, int part_idx,
|
|
int merge_idx, MvField *mv)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
enum InterPredIdc inter_pred_idc = PRED_L0;
|
|
int mvp_flag;
|
|
|
|
ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH);
|
|
if (s->sh.slice_type == HEVC_SLICE_B)
|
|
inter_pred_idc = ff_hevc_inter_pred_idc_decode(s, nPbW, nPbH);
|
|
|
|
if (inter_pred_idc != PRED_L1) {
|
|
if (s->sh.nb_refs[L0])
|
|
mv->ref_idx[0]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L0]);
|
|
|
|
mv->pred_flag[0] = 1;
|
|
hls_mvd_coding(s, x0, y0, 0);
|
|
mvp_flag = ff_hevc_mvp_lx_flag_decode(s);
|
|
ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
|
|
part_idx, merge_idx, mv, mvp_flag, 0);
|
|
mv->mv[0].x += lc->pu.mvd.x;
|
|
mv->mv[0].y += lc->pu.mvd.y;
|
|
}
|
|
|
|
if (inter_pred_idc != PRED_L0) {
|
|
if (s->sh.nb_refs[L1])
|
|
mv->ref_idx[1]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L1]);
|
|
|
|
if (s->sh.mvd_l1_zero_flag == 1 && inter_pred_idc == PRED_BI) {
|
|
AV_ZERO32(&lc->pu.mvd);
|
|
} else {
|
|
hls_mvd_coding(s, x0, y0, 1);
|
|
}
|
|
|
|
mv->pred_flag[1] = 1;
|
|
mvp_flag = ff_hevc_mvp_lx_flag_decode(s);
|
|
ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
|
|
part_idx, merge_idx, mv, mvp_flag, 1);
|
|
mv->mv[1].x += lc->pu.mvd.x;
|
|
mv->mv[1].y += lc->pu.mvd.y;
|
|
}
|
|
}
|
|
|
|
static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
|
|
int nPbW, int nPbH,
|
|
int log2_cb_size, int partIdx)
|
|
{
|
|
static const int pred_indices[] = {
|
|
[4] = 0, [8] = 1, [12] = 2, [16] = 3, [24] = 4, [32] = 5, [48] = 6, [64] = 7,
|
|
};
|
|
const int pred_idx = pred_indices[nPbW];
|
|
|
|
#define POS(c_idx, x, y) \
|
|
&s->frame->data[c_idx][((y) >> s->ps.sps->vshift[c_idx]) * s->frame->linesize[c_idx] + \
|
|
(((x) >> s->ps.sps->hshift[c_idx]) << s->ps.sps->pixel_shift)]
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
int merge_idx = 0;
|
|
struct MvField current_mv = {{{ 0 }}};
|
|
|
|
int min_pu_width = s->ps.sps->min_pu_width;
|
|
int weighted_pred = (s->sh.slice_type == HEVC_SLICE_P && s->ps.pps->weighted_pred_flag) ||
|
|
(s->sh.slice_type == HEVC_SLICE_B && s->ps.pps->weighted_bipred_flag);
|
|
|
|
MvField *tab_mvf = s->ref->tab_mvf;
|
|
RefPicList *refPicList = s->ref->refPicList;
|
|
HEVCFrame *ref0, *ref1;
|
|
|
|
ptrdiff_t tmpstride = MAX_PB_SIZE * sizeof(int16_t);
|
|
|
|
uint8_t *dst0 = POS(0, x0, y0);
|
|
uint8_t *dst1 = POS(1, x0, y0);
|
|
uint8_t *dst2 = POS(2, x0, y0);
|
|
int log2_min_cb_size = s->ps.sps->log2_min_cb_size;
|
|
int min_cb_width = s->ps.sps->min_cb_width;
|
|
int x_cb = x0 >> log2_min_cb_size;
|
|
int y_cb = y0 >> log2_min_cb_size;
|
|
int x_pu, y_pu;
|
|
int i, j;
|
|
|
|
int skip_flag = SAMPLE_CTB(s->skip_flag, x_cb, y_cb);
|
|
|
|
if (!skip_flag)
|
|
lc->pu.merge_flag = ff_hevc_merge_flag_decode(s);
|
|
|
|
if (skip_flag || lc->pu.merge_flag) {
|
|
if (s->sh.max_num_merge_cand > 1)
|
|
merge_idx = ff_hevc_merge_idx_decode(s);
|
|
else
|
|
merge_idx = 0;
|
|
|
|
ff_hevc_luma_mv_merge_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
|
|
partIdx, merge_idx, ¤t_mv);
|
|
} else {
|
|
hevc_luma_mv_mpv_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
|
|
partIdx, merge_idx, ¤t_mv);
|
|
}
|
|
|
|
x_pu = x0 >> s->ps.sps->log2_min_pu_size;
|
|
y_pu = y0 >> s->ps.sps->log2_min_pu_size;
|
|
|
|
for (j = 0; j < nPbH >> s->ps.sps->log2_min_pu_size; j++)
|
|
for (i = 0; i < nPbW >> s->ps.sps->log2_min_pu_size; i++)
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv;
|
|
|
|
if (current_mv.pred_flag[0]) {
|
|
ref0 = refPicList[0].ref[current_mv.ref_idx[0]];
|
|
if (!ref0)
|
|
return;
|
|
hevc_await_progress(s, ref0, ¤t_mv.mv[0], y0, nPbH);
|
|
}
|
|
if (current_mv.pred_flag[1]) {
|
|
ref1 = refPicList[1].ref[current_mv.ref_idx[1]];
|
|
if (!ref1)
|
|
return;
|
|
hevc_await_progress(s, ref1, ¤t_mv.mv[1], y0, nPbH);
|
|
}
|
|
|
|
if (current_mv.pred_flag[0] && !current_mv.pred_flag[1]) {
|
|
LOCAL_ALIGNED_16(int16_t, tmp, [MAX_PB_SIZE * MAX_PB_SIZE]);
|
|
LOCAL_ALIGNED_16(int16_t, tmp2, [MAX_PB_SIZE * MAX_PB_SIZE]);
|
|
|
|
luma_mc(s, tmp, tmpstride, ref0->frame,
|
|
¤t_mv.mv[0], x0, y0, nPbW, nPbH, pred_idx);
|
|
|
|
if (weighted_pred) {
|
|
s->hevcdsp.weighted_pred[pred_idx](s->sh.luma_log2_weight_denom,
|
|
s->sh.luma_weight_l0[current_mv.ref_idx[0]],
|
|
s->sh.luma_offset_l0[current_mv.ref_idx[0]],
|
|
dst0, s->frame->linesize[0], tmp,
|
|
tmpstride, nPbH);
|
|
} else {
|
|
s->hevcdsp.put_unweighted_pred[pred_idx](dst0, s->frame->linesize[0], tmp, tmpstride, nPbH);
|
|
}
|
|
chroma_mc(s, tmp, tmp2, tmpstride, ref0->frame,
|
|
¤t_mv.mv[0], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2, pred_idx);
|
|
|
|
if (weighted_pred) {
|
|
s->hevcdsp.weighted_pred_chroma[pred_idx](s->sh.chroma_log2_weight_denom,
|
|
s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0],
|
|
s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0],
|
|
dst1, s->frame->linesize[1], tmp, tmpstride,
|
|
nPbH / 2);
|
|
s->hevcdsp.weighted_pred_chroma[pred_idx](s->sh.chroma_log2_weight_denom,
|
|
s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1],
|
|
s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1],
|
|
dst2, s->frame->linesize[2], tmp2, tmpstride,
|
|
nPbH / 2);
|
|
} else {
|
|
s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst1, s->frame->linesize[1], tmp, tmpstride, nPbH / 2);
|
|
s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst2, s->frame->linesize[2], tmp2, tmpstride, nPbH / 2);
|
|
}
|
|
} else if (!current_mv.pred_flag[0] && current_mv.pred_flag[1]) {
|
|
LOCAL_ALIGNED_16(int16_t, tmp, [MAX_PB_SIZE * MAX_PB_SIZE]);
|
|
LOCAL_ALIGNED_16(int16_t, tmp2, [MAX_PB_SIZE * MAX_PB_SIZE]);
|
|
|
|
luma_mc(s, tmp, tmpstride, ref1->frame,
|
|
¤t_mv.mv[1], x0, y0, nPbW, nPbH, pred_idx);
|
|
|
|
if (weighted_pred) {
|
|
s->hevcdsp.weighted_pred[pred_idx](s->sh.luma_log2_weight_denom,
|
|
s->sh.luma_weight_l1[current_mv.ref_idx[1]],
|
|
s->sh.luma_offset_l1[current_mv.ref_idx[1]],
|
|
dst0, s->frame->linesize[0], tmp, tmpstride,
|
|
nPbH);
|
|
} else {
|
|
s->hevcdsp.put_unweighted_pred[pred_idx](dst0, s->frame->linesize[0], tmp, tmpstride, nPbH);
|
|
}
|
|
|
|
chroma_mc(s, tmp, tmp2, tmpstride, ref1->frame,
|
|
¤t_mv.mv[1], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2, pred_idx);
|
|
|
|
if (weighted_pred) {
|
|
s->hevcdsp.weighted_pred_chroma[pred_idx](s->sh.chroma_log2_weight_denom,
|
|
s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0],
|
|
s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0],
|
|
dst1, s->frame->linesize[1], tmp, tmpstride, nPbH/2);
|
|
s->hevcdsp.weighted_pred_chroma[pred_idx](s->sh.chroma_log2_weight_denom,
|
|
s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1],
|
|
s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1],
|
|
dst2, s->frame->linesize[2], tmp2, tmpstride, nPbH/2);
|
|
} else {
|
|
s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst1, s->frame->linesize[1], tmp, tmpstride, nPbH / 2);
|
|
s->hevcdsp.put_unweighted_pred_chroma[pred_idx](dst2, s->frame->linesize[2], tmp2, tmpstride, nPbH / 2);
|
|
}
|
|
} else if (current_mv.pred_flag[0] && current_mv.pred_flag[1]) {
|
|
LOCAL_ALIGNED_16(int16_t, tmp, [MAX_PB_SIZE * MAX_PB_SIZE]);
|
|
LOCAL_ALIGNED_16(int16_t, tmp2, [MAX_PB_SIZE * MAX_PB_SIZE]);
|
|
LOCAL_ALIGNED_16(int16_t, tmp3, [MAX_PB_SIZE * MAX_PB_SIZE]);
|
|
LOCAL_ALIGNED_16(int16_t, tmp4, [MAX_PB_SIZE * MAX_PB_SIZE]);
|
|
|
|
luma_mc(s, tmp, tmpstride, ref0->frame,
|
|
¤t_mv.mv[0], x0, y0, nPbW, nPbH, pred_idx);
|
|
luma_mc(s, tmp2, tmpstride, ref1->frame,
|
|
¤t_mv.mv[1], x0, y0, nPbW, nPbH, pred_idx);
|
|
|
|
if (weighted_pred) {
|
|
s->hevcdsp.weighted_pred_avg[pred_idx](s->sh.luma_log2_weight_denom,
|
|
s->sh.luma_weight_l0[current_mv.ref_idx[0]],
|
|
s->sh.luma_weight_l1[current_mv.ref_idx[1]],
|
|
s->sh.luma_offset_l0[current_mv.ref_idx[0]],
|
|
s->sh.luma_offset_l1[current_mv.ref_idx[1]],
|
|
dst0, s->frame->linesize[0],
|
|
tmp, tmp2, tmpstride, nPbH);
|
|
} else {
|
|
s->hevcdsp.put_unweighted_pred_avg[pred_idx](dst0, s->frame->linesize[0],
|
|
tmp, tmp2, tmpstride, nPbH);
|
|
}
|
|
|
|
chroma_mc(s, tmp, tmp2, tmpstride, ref0->frame,
|
|
¤t_mv.mv[0], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2, pred_idx);
|
|
chroma_mc(s, tmp3, tmp4, tmpstride, ref1->frame,
|
|
¤t_mv.mv[1], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2, pred_idx);
|
|
|
|
if (weighted_pred) {
|
|
s->hevcdsp.weighted_pred_avg_chroma[pred_idx](s->sh.chroma_log2_weight_denom,
|
|
s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0],
|
|
s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0],
|
|
s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0],
|
|
s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0],
|
|
dst1, s->frame->linesize[1], tmp, tmp3,
|
|
tmpstride, nPbH / 2);
|
|
s->hevcdsp.weighted_pred_avg_chroma[pred_idx](s->sh.chroma_log2_weight_denom,
|
|
s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1],
|
|
s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1],
|
|
s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1],
|
|
s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1],
|
|
dst2, s->frame->linesize[2], tmp2, tmp4,
|
|
tmpstride, nPbH / 2);
|
|
} else {
|
|
s->hevcdsp.put_unweighted_pred_avg_chroma[pred_idx](dst1, s->frame->linesize[1], tmp, tmp3, tmpstride, nPbH/2);
|
|
s->hevcdsp.put_unweighted_pred_avg_chroma[pred_idx](dst2, s->frame->linesize[2], tmp2, tmp4, tmpstride, nPbH/2);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 8.4.1
|
|
*/
|
|
static int luma_intra_pred_mode(HEVCContext *s, int x0, int y0, int pu_size,
|
|
int prev_intra_luma_pred_flag)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
int x_pu = x0 >> s->ps.sps->log2_min_pu_size;
|
|
int y_pu = y0 >> s->ps.sps->log2_min_pu_size;
|
|
int min_pu_width = s->ps.sps->min_pu_width;
|
|
int size_in_pus = pu_size >> s->ps.sps->log2_min_pu_size;
|
|
int x0b = x0 & ((1 << s->ps.sps->log2_ctb_size) - 1);
|
|
int y0b = y0 & ((1 << s->ps.sps->log2_ctb_size) - 1);
|
|
|
|
int cand_up = (lc->ctb_up_flag || y0b) ?
|
|
s->tab_ipm[(y_pu - 1) * min_pu_width + x_pu] : INTRA_DC;
|
|
int cand_left = (lc->ctb_left_flag || x0b) ?
|
|
s->tab_ipm[y_pu * min_pu_width + x_pu - 1] : INTRA_DC;
|
|
|
|
int y_ctb = (y0 >> (s->ps.sps->log2_ctb_size)) << (s->ps.sps->log2_ctb_size);
|
|
|
|
MvField *tab_mvf = s->ref->tab_mvf;
|
|
int intra_pred_mode;
|
|
int candidate[3];
|
|
int i, j;
|
|
|
|
// intra_pred_mode prediction does not cross vertical CTB boundaries
|
|
if ((y0 - 1) < y_ctb)
|
|
cand_up = INTRA_DC;
|
|
|
|
if (cand_left == cand_up) {
|
|
if (cand_left < 2) {
|
|
candidate[0] = INTRA_PLANAR;
|
|
candidate[1] = INTRA_DC;
|
|
candidate[2] = INTRA_ANGULAR_26;
|
|
} else {
|
|
candidate[0] = cand_left;
|
|
candidate[1] = 2 + ((cand_left - 2 - 1 + 32) & 31);
|
|
candidate[2] = 2 + ((cand_left - 2 + 1) & 31);
|
|
}
|
|
} else {
|
|
candidate[0] = cand_left;
|
|
candidate[1] = cand_up;
|
|
if (candidate[0] != INTRA_PLANAR && candidate[1] != INTRA_PLANAR) {
|
|
candidate[2] = INTRA_PLANAR;
|
|
} else if (candidate[0] != INTRA_DC && candidate[1] != INTRA_DC) {
|
|
candidate[2] = INTRA_DC;
|
|
} else {
|
|
candidate[2] = INTRA_ANGULAR_26;
|
|
}
|
|
}
|
|
|
|
if (prev_intra_luma_pred_flag) {
|
|
intra_pred_mode = candidate[lc->pu.mpm_idx];
|
|
} else {
|
|
if (candidate[0] > candidate[1])
|
|
FFSWAP(uint8_t, candidate[0], candidate[1]);
|
|
if (candidate[0] > candidate[2])
|
|
FFSWAP(uint8_t, candidate[0], candidate[2]);
|
|
if (candidate[1] > candidate[2])
|
|
FFSWAP(uint8_t, candidate[1], candidate[2]);
|
|
|
|
intra_pred_mode = lc->pu.rem_intra_luma_pred_mode;
|
|
for (i = 0; i < 3; i++)
|
|
if (intra_pred_mode >= candidate[i])
|
|
intra_pred_mode++;
|
|
}
|
|
|
|
/* write the intra prediction units into the mv array */
|
|
if (!size_in_pus)
|
|
size_in_pus = 1;
|
|
for (i = 0; i < size_in_pus; i++) {
|
|
memset(&s->tab_ipm[(y_pu + i) * min_pu_width + x_pu],
|
|
intra_pred_mode, size_in_pus);
|
|
|
|
for (j = 0; j < size_in_pus; j++) {
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].is_intra = 1;
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].pred_flag[0] = 0;
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].pred_flag[1] = 0;
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].ref_idx[0] = 0;
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].ref_idx[1] = 0;
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].mv[0].x = 0;
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].mv[0].y = 0;
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].mv[1].x = 0;
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].mv[1].y = 0;
|
|
}
|
|
}
|
|
|
|
return intra_pred_mode;
|
|
}
|
|
|
|
static av_always_inline void set_ct_depth(HEVCContext *s, int x0, int y0,
|
|
int log2_cb_size, int ct_depth)
|
|
{
|
|
int length = (1 << log2_cb_size) >> s->ps.sps->log2_min_cb_size;
|
|
int x_cb = x0 >> s->ps.sps->log2_min_cb_size;
|
|
int y_cb = y0 >> s->ps.sps->log2_min_cb_size;
|
|
int y;
|
|
|
|
for (y = 0; y < length; y++)
|
|
memset(&s->tab_ct_depth[(y_cb + y) * s->ps.sps->min_cb_width + x_cb],
|
|
ct_depth, length);
|
|
}
|
|
|
|
static void intra_prediction_unit(HEVCContext *s, int x0, int y0,
|
|
int log2_cb_size)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
static const uint8_t intra_chroma_table[4] = { 0, 26, 10, 1 };
|
|
uint8_t prev_intra_luma_pred_flag[4];
|
|
int split = lc->cu.part_mode == PART_NxN;
|
|
int pb_size = (1 << log2_cb_size) >> split;
|
|
int side = split + 1;
|
|
int chroma_mode;
|
|
int i, j;
|
|
|
|
for (i = 0; i < side; i++)
|
|
for (j = 0; j < side; j++)
|
|
prev_intra_luma_pred_flag[2 * i + j] = ff_hevc_prev_intra_luma_pred_flag_decode(s);
|
|
|
|
for (i = 0; i < side; i++) {
|
|
for (j = 0; j < side; j++) {
|
|
if (prev_intra_luma_pred_flag[2 * i + j])
|
|
lc->pu.mpm_idx = ff_hevc_mpm_idx_decode(s);
|
|
else
|
|
lc->pu.rem_intra_luma_pred_mode = ff_hevc_rem_intra_luma_pred_mode_decode(s);
|
|
|
|
lc->pu.intra_pred_mode[2 * i + j] =
|
|
luma_intra_pred_mode(s, x0 + pb_size * j, y0 + pb_size * i, pb_size,
|
|
prev_intra_luma_pred_flag[2 * i + j]);
|
|
}
|
|
}
|
|
|
|
chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s);
|
|
if (chroma_mode != 4) {
|
|
if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode])
|
|
lc->pu.intra_pred_mode_c = 34;
|
|
else
|
|
lc->pu.intra_pred_mode_c = intra_chroma_table[chroma_mode];
|
|
} else {
|
|
lc->pu.intra_pred_mode_c = lc->pu.intra_pred_mode[0];
|
|
}
|
|
}
|
|
|
|
static void intra_prediction_unit_default_value(HEVCContext *s,
|
|
int x0, int y0,
|
|
int log2_cb_size)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
int pb_size = 1 << log2_cb_size;
|
|
int size_in_pus = pb_size >> s->ps.sps->log2_min_pu_size;
|
|
int min_pu_width = s->ps.sps->min_pu_width;
|
|
MvField *tab_mvf = s->ref->tab_mvf;
|
|
int x_pu = x0 >> s->ps.sps->log2_min_pu_size;
|
|
int y_pu = y0 >> s->ps.sps->log2_min_pu_size;
|
|
int j, k;
|
|
|
|
if (size_in_pus == 0)
|
|
size_in_pus = 1;
|
|
for (j = 0; j < size_in_pus; j++) {
|
|
memset(&s->tab_ipm[(y_pu + j) * min_pu_width + x_pu], INTRA_DC, size_in_pus);
|
|
for (k = 0; k < size_in_pus; k++)
|
|
tab_mvf[(y_pu + j) * min_pu_width + x_pu + k].is_intra = lc->cu.pred_mode == MODE_INTRA;
|
|
}
|
|
}
|
|
|
|
static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
|
|
{
|
|
int cb_size = 1 << log2_cb_size;
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
int log2_min_cb_size = s->ps.sps->log2_min_cb_size;
|
|
int length = cb_size >> log2_min_cb_size;
|
|
int min_cb_width = s->ps.sps->min_cb_width;
|
|
int x_cb = x0 >> log2_min_cb_size;
|
|
int y_cb = y0 >> log2_min_cb_size;
|
|
int x, y, ret;
|
|
|
|
lc->cu.x = x0;
|
|
lc->cu.y = y0;
|
|
lc->cu.pred_mode = MODE_INTRA;
|
|
lc->cu.part_mode = PART_2Nx2N;
|
|
lc->cu.intra_split_flag = 0;
|
|
|
|
SAMPLE_CTB(s->skip_flag, x_cb, y_cb) = 0;
|
|
for (x = 0; x < 4; x++)
|
|
lc->pu.intra_pred_mode[x] = 1;
|
|
if (s->ps.pps->transquant_bypass_enable_flag) {
|
|
lc->cu.cu_transquant_bypass_flag = ff_hevc_cu_transquant_bypass_flag_decode(s);
|
|
if (lc->cu.cu_transquant_bypass_flag)
|
|
set_deblocking_bypass(s, x0, y0, log2_cb_size);
|
|
} else
|
|
lc->cu.cu_transquant_bypass_flag = 0;
|
|
|
|
if (s->sh.slice_type != HEVC_SLICE_I) {
|
|
uint8_t skip_flag = ff_hevc_skip_flag_decode(s, x0, y0, x_cb, y_cb);
|
|
|
|
x = y_cb * min_cb_width + x_cb;
|
|
for (y = 0; y < length; y++) {
|
|
memset(&s->skip_flag[x], skip_flag, length);
|
|
x += min_cb_width;
|
|
}
|
|
lc->cu.pred_mode = skip_flag ? MODE_SKIP : MODE_INTER;
|
|
}
|
|
|
|
if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) {
|
|
hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0);
|
|
intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
|
|
|
|
if (!s->sh.disable_deblocking_filter_flag)
|
|
ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size);
|
|
} else {
|
|
int pcm_flag = 0;
|
|
|
|
if (s->sh.slice_type != HEVC_SLICE_I)
|
|
lc->cu.pred_mode = ff_hevc_pred_mode_decode(s);
|
|
if (lc->cu.pred_mode != MODE_INTRA ||
|
|
log2_cb_size == s->ps.sps->log2_min_cb_size) {
|
|
lc->cu.part_mode = ff_hevc_part_mode_decode(s, log2_cb_size);
|
|
lc->cu.intra_split_flag = lc->cu.part_mode == PART_NxN &&
|
|
lc->cu.pred_mode == MODE_INTRA;
|
|
}
|
|
|
|
if (lc->cu.pred_mode == MODE_INTRA) {
|
|
if (lc->cu.part_mode == PART_2Nx2N && s->ps.sps->pcm_enabled_flag &&
|
|
log2_cb_size >= s->ps.sps->pcm.log2_min_pcm_cb_size &&
|
|
log2_cb_size <= s->ps.sps->pcm.log2_max_pcm_cb_size) {
|
|
pcm_flag = ff_hevc_pcm_flag_decode(s);
|
|
}
|
|
if (pcm_flag) {
|
|
intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
|
|
ret = hls_pcm_sample(s, x0, y0, log2_cb_size);
|
|
if (s->ps.sps->pcm.loop_filter_disable_flag)
|
|
set_deblocking_bypass(s, x0, y0, log2_cb_size);
|
|
|
|
if (ret < 0)
|
|
return ret;
|
|
} else {
|
|
intra_prediction_unit(s, x0, y0, log2_cb_size);
|
|
}
|
|
} else {
|
|
intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
|
|
switch (lc->cu.part_mode) {
|
|
case PART_2Nx2N:
|
|
hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0);
|
|
break;
|
|
case PART_2NxN:
|
|
hls_prediction_unit(s, x0, y0, cb_size, cb_size / 2, log2_cb_size, 0);
|
|
hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1);
|
|
break;
|
|
case PART_Nx2N:
|
|
hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size, log2_cb_size, 0);
|
|
hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1);
|
|
break;
|
|
case PART_2NxnU:
|
|
hls_prediction_unit(s, x0, y0, cb_size, cb_size / 4, log2_cb_size, 0);
|
|
hls_prediction_unit(s, x0, y0 + cb_size / 4, cb_size, cb_size * 3 / 4, log2_cb_size, 1);
|
|
break;
|
|
case PART_2NxnD:
|
|
hls_prediction_unit(s, x0, y0, cb_size, cb_size * 3 / 4, log2_cb_size, 0);
|
|
hls_prediction_unit(s, x0, y0 + cb_size * 3 / 4, cb_size, cb_size / 4, log2_cb_size, 1);
|
|
break;
|
|
case PART_nLx2N:
|
|
hls_prediction_unit(s, x0, y0, cb_size / 4, cb_size, log2_cb_size, 0);
|
|
hls_prediction_unit(s, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1);
|
|
break;
|
|
case PART_nRx2N:
|
|
hls_prediction_unit(s, x0, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 0);
|
|
hls_prediction_unit(s, x0 + cb_size * 3 / 4, y0, cb_size / 4, cb_size, log2_cb_size, 1);
|
|
break;
|
|
case PART_NxN:
|
|
hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size / 2, log2_cb_size, 0);
|
|
hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size / 2, log2_cb_size, 1);
|
|
hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2);
|
|
hls_prediction_unit(s, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!pcm_flag) {
|
|
int rqt_root_cbf = 1;
|
|
|
|
if (lc->cu.pred_mode != MODE_INTRA &&
|
|
!(lc->cu.part_mode == PART_2Nx2N && lc->pu.merge_flag)) {
|
|
rqt_root_cbf = ff_hevc_no_residual_syntax_flag_decode(s);
|
|
}
|
|
if (rqt_root_cbf) {
|
|
lc->cu.max_trafo_depth = lc->cu.pred_mode == MODE_INTRA ?
|
|
s->ps.sps->max_transform_hierarchy_depth_intra + lc->cu.intra_split_flag :
|
|
s->ps.sps->max_transform_hierarchy_depth_inter;
|
|
ret = hls_transform_tree(s, x0, y0, x0, y0, x0, y0,
|
|
log2_cb_size,
|
|
log2_cb_size, 0, 0, 0, 0);
|
|
if (ret < 0)
|
|
return ret;
|
|
} else {
|
|
if (!s->sh.disable_deblocking_filter_flag)
|
|
ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (s->ps.pps->cu_qp_delta_enabled_flag && lc->tu.is_cu_qp_delta_coded == 0)
|
|
ff_hevc_set_qPy(s, x0, y0, x0, y0, log2_cb_size);
|
|
|
|
x = y_cb * min_cb_width + x_cb;
|
|
for (y = 0; y < length; y++) {
|
|
memset(&s->qp_y_tab[x], lc->qp_y, length);
|
|
x += min_cb_width;
|
|
}
|
|
|
|
set_ct_depth(s, x0, y0, log2_cb_size, lc->ct.depth);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hls_coding_quadtree(HEVCContext *s, int x0, int y0,
|
|
int log2_cb_size, int cb_depth)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
const int cb_size = 1 << log2_cb_size;
|
|
int split_cu;
|
|
|
|
lc->ct.depth = cb_depth;
|
|
if (x0 + cb_size <= s->ps.sps->width &&
|
|
y0 + cb_size <= s->ps.sps->height &&
|
|
log2_cb_size > s->ps.sps->log2_min_cb_size) {
|
|
split_cu = ff_hevc_split_coding_unit_flag_decode(s, cb_depth, x0, y0);
|
|
} else {
|
|
split_cu = (log2_cb_size > s->ps.sps->log2_min_cb_size);
|
|
}
|
|
if (s->ps.pps->cu_qp_delta_enabled_flag &&
|
|
log2_cb_size >= s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_qp_delta_depth) {
|
|
lc->tu.is_cu_qp_delta_coded = 0;
|
|
lc->tu.cu_qp_delta = 0;
|
|
}
|
|
|
|
if (split_cu) {
|
|
const int cb_size_split = cb_size >> 1;
|
|
const int x1 = x0 + cb_size_split;
|
|
const int y1 = y0 + cb_size_split;
|
|
|
|
log2_cb_size--;
|
|
cb_depth++;
|
|
|
|
#define SUBDIVIDE(x, y) \
|
|
do { \
|
|
if (x < s->ps.sps->width && y < s->ps.sps->height) { \
|
|
int ret = hls_coding_quadtree(s, x, y, log2_cb_size, cb_depth);\
|
|
if (ret < 0) \
|
|
return ret; \
|
|
} \
|
|
} while (0)
|
|
|
|
SUBDIVIDE(x0, y0);
|
|
SUBDIVIDE(x1, y0);
|
|
SUBDIVIDE(x0, y1);
|
|
SUBDIVIDE(x1, y1);
|
|
} else {
|
|
int ret = hls_coding_unit(s, x0, y0, log2_cb_size);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb,
|
|
int ctb_addr_ts)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
int ctb_size = 1 << s->ps.sps->log2_ctb_size;
|
|
int ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts];
|
|
int ctb_addr_in_slice = ctb_addr_rs - s->sh.slice_addr;
|
|
|
|
s->tab_slice_address[ctb_addr_rs] = s->sh.slice_addr;
|
|
|
|
if (s->ps.pps->entropy_coding_sync_enabled_flag) {
|
|
if (x_ctb == 0 && (y_ctb & (ctb_size - 1)) == 0)
|
|
lc->first_qp_group = 1;
|
|
lc->end_of_tiles_x = s->ps.sps->width;
|
|
} else if (s->ps.pps->tiles_enabled_flag) {
|
|
if (ctb_addr_ts && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[ctb_addr_ts - 1]) {
|
|
int idxX = s->ps.pps->col_idxX[x_ctb >> s->ps.sps->log2_ctb_size];
|
|
lc->start_of_tiles_x = x_ctb;
|
|
lc->end_of_tiles_x = x_ctb + (s->ps.pps->column_width[idxX] << s->ps.sps->log2_ctb_size);
|
|
lc->first_qp_group = 1;
|
|
}
|
|
} else {
|
|
lc->end_of_tiles_x = s->ps.sps->width;
|
|
}
|
|
|
|
lc->end_of_tiles_y = FFMIN(y_ctb + ctb_size, s->ps.sps->height);
|
|
|
|
lc->boundary_flags = 0;
|
|
if (s->ps.pps->tiles_enabled_flag) {
|
|
if (x_ctb > 0 && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - 1]])
|
|
lc->boundary_flags |= BOUNDARY_LEFT_TILE;
|
|
if (x_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - 1])
|
|
lc->boundary_flags |= BOUNDARY_LEFT_SLICE;
|
|
if (y_ctb > 0 && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - s->ps.sps->ctb_width]])
|
|
lc->boundary_flags |= BOUNDARY_UPPER_TILE;
|
|
if (y_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - s->ps.sps->ctb_width])
|
|
lc->boundary_flags |= BOUNDARY_UPPER_SLICE;
|
|
} else {
|
|
if (!ctb_addr_in_slice)
|
|
lc->boundary_flags |= BOUNDARY_LEFT_SLICE;
|
|
if (ctb_addr_in_slice < s->ps.sps->ctb_width)
|
|
lc->boundary_flags |= BOUNDARY_UPPER_SLICE;
|
|
}
|
|
|
|
lc->ctb_left_flag = ((x_ctb > 0) && (ctb_addr_in_slice > 0) && !(lc->boundary_flags & BOUNDARY_LEFT_TILE));
|
|
lc->ctb_up_flag = ((y_ctb > 0) && (ctb_addr_in_slice >= s->ps.sps->ctb_width) && !(lc->boundary_flags & BOUNDARY_UPPER_TILE));
|
|
lc->ctb_up_right_flag = ((y_ctb > 0) && (ctb_addr_in_slice+1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs+1 - s->ps.sps->ctb_width]]));
|
|
lc->ctb_up_left_flag = ((x_ctb > 0) && (y_ctb > 0) && (ctb_addr_in_slice-1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs-1 - s->ps.sps->ctb_width]]));
|
|
}
|
|
|
|
static int hls_slice_data(HEVCContext *s)
|
|
{
|
|
int ctb_size = 1 << s->ps.sps->log2_ctb_size;
|
|
int more_data = 1;
|
|
int x_ctb = 0;
|
|
int y_ctb = 0;
|
|
int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs];
|
|
int ret;
|
|
|
|
while (more_data && ctb_addr_ts < s->ps.sps->ctb_size) {
|
|
int ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts];
|
|
|
|
x_ctb = (ctb_addr_rs % ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size;
|
|
y_ctb = (ctb_addr_rs / ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size;
|
|
hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts);
|
|
|
|
ff_hevc_cabac_init(s, ctb_addr_ts);
|
|
|
|
hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size);
|
|
|
|
s->deblock[ctb_addr_rs].beta_offset = s->sh.beta_offset;
|
|
s->deblock[ctb_addr_rs].tc_offset = s->sh.tc_offset;
|
|
s->filter_slice_edges[ctb_addr_rs] = s->sh.slice_loop_filter_across_slices_enabled_flag;
|
|
|
|
ret = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0);
|
|
if (ret < 0)
|
|
return ret;
|
|
more_data = !ff_hevc_end_of_slice_flag_decode(s);
|
|
|
|
ctb_addr_ts++;
|
|
ff_hevc_save_states(s, ctb_addr_ts);
|
|
ff_hevc_hls_filters(s, x_ctb, y_ctb, ctb_size);
|
|
}
|
|
|
|
if (x_ctb + ctb_size >= s->ps.sps->width &&
|
|
y_ctb + ctb_size >= s->ps.sps->height)
|
|
ff_hevc_hls_filter(s, x_ctb, y_ctb);
|
|
|
|
return ctb_addr_ts;
|
|
}
|
|
|
|
static void restore_tqb_pixels(HEVCContext *s)
|
|
{
|
|
int min_pu_size = 1 << s->ps.sps->log2_min_pu_size;
|
|
int x, y, c_idx;
|
|
|
|
for (c_idx = 0; c_idx < 3; c_idx++) {
|
|
ptrdiff_t stride = s->frame->linesize[c_idx];
|
|
int hshift = s->ps.sps->hshift[c_idx];
|
|
int vshift = s->ps.sps->vshift[c_idx];
|
|
for (y = 0; y < s->ps.sps->min_pu_height; y++) {
|
|
for (x = 0; x < s->ps.sps->min_pu_width; x++) {
|
|
if (s->is_pcm[y * s->ps.sps->min_pu_width + x]) {
|
|
int n;
|
|
int len = min_pu_size >> hshift;
|
|
uint8_t *src = &s->frame->data[c_idx][((y << s->ps.sps->log2_min_pu_size) >> vshift) * stride + (((x << s->ps.sps->log2_min_pu_size) >> hshift) << s->ps.sps->pixel_shift)];
|
|
uint8_t *dst = &s->sao_frame->data[c_idx][((y << s->ps.sps->log2_min_pu_size) >> vshift) * stride + (((x << s->ps.sps->log2_min_pu_size) >> hshift) << s->ps.sps->pixel_shift)];
|
|
for (n = 0; n < (min_pu_size >> vshift); n++) {
|
|
memcpy(dst, src, len);
|
|
src += stride;
|
|
dst += stride;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int set_side_data(HEVCContext *s)
|
|
{
|
|
AVFrame *out = s->ref->frame;
|
|
|
|
if (s->sei.frame_packing.present &&
|
|
s->sei.frame_packing.arrangement_type >= 3 &&
|
|
s->sei.frame_packing.arrangement_type <= 5 &&
|
|
s->sei.frame_packing.content_interpretation_type > 0 &&
|
|
s->sei.frame_packing.content_interpretation_type < 3) {
|
|
AVStereo3D *stereo = av_stereo3d_create_side_data(out);
|
|
if (!stereo)
|
|
return AVERROR(ENOMEM);
|
|
|
|
switch (s->sei.frame_packing.arrangement_type) {
|
|
case 3:
|
|
if (s->sei.frame_packing.quincunx_subsampling)
|
|
stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX;
|
|
else
|
|
stereo->type = AV_STEREO3D_SIDEBYSIDE;
|
|
break;
|
|
case 4:
|
|
stereo->type = AV_STEREO3D_TOPBOTTOM;
|
|
break;
|
|
case 5:
|
|
stereo->type = AV_STEREO3D_FRAMESEQUENCE;
|
|
break;
|
|
}
|
|
|
|
if (s->sei.frame_packing.content_interpretation_type == 2)
|
|
stereo->flags = AV_STEREO3D_FLAG_INVERT;
|
|
}
|
|
|
|
if (s->sei.display_orientation.present &&
|
|
(s->sei.display_orientation.anticlockwise_rotation ||
|
|
s->sei.display_orientation.hflip || s->sei.display_orientation.vflip)) {
|
|
double angle = s->sei.display_orientation.anticlockwise_rotation * 360 / (double) (1 << 16);
|
|
AVFrameSideData *rotation = av_frame_new_side_data(out,
|
|
AV_FRAME_DATA_DISPLAYMATRIX,
|
|
sizeof(int32_t) * 9);
|
|
if (!rotation)
|
|
return AVERROR(ENOMEM);
|
|
|
|
av_display_rotation_set((int32_t *)rotation->data, angle);
|
|
av_display_matrix_flip((int32_t *)rotation->data,
|
|
s->sei.display_orientation.hflip,
|
|
s->sei.display_orientation.vflip);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hevc_frame_start(HEVCContext *s)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
int ret;
|
|
|
|
memset(s->horizontal_bs, 0, 2 * s->bs_width * (s->bs_height + 1));
|
|
memset(s->vertical_bs, 0, 2 * s->bs_width * (s->bs_height + 1));
|
|
memset(s->cbf_luma, 0, s->ps.sps->min_tb_width * s->ps.sps->min_tb_height);
|
|
memset(s->is_pcm, 0, s->ps.sps->min_pu_width * s->ps.sps->min_pu_height);
|
|
|
|
lc->start_of_tiles_x = 0;
|
|
s->is_decoded = 0;
|
|
s->first_nal_type = s->nal_unit_type;
|
|
|
|
if (s->ps.pps->tiles_enabled_flag)
|
|
lc->end_of_tiles_x = s->ps.pps->column_width[0] << s->ps.sps->log2_ctb_size;
|
|
|
|
ret = ff_hevc_set_new_ref(s, s->ps.sps->sao_enabled ? &s->sao_frame : &s->frame,
|
|
s->poc);
|
|
if (ret < 0)
|
|
goto fail;
|
|
|
|
ret = ff_hevc_frame_rps(s);
|
|
if (ret < 0) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "Error constructing the frame RPS.\n");
|
|
goto fail;
|
|
}
|
|
|
|
s->ref->frame->key_frame = IS_IRAP(s);
|
|
|
|
ret = set_side_data(s);
|
|
if (ret < 0)
|
|
goto fail;
|
|
|
|
av_frame_unref(s->output_frame);
|
|
ret = ff_hevc_output_frame(s, s->output_frame, 0);
|
|
if (ret < 0)
|
|
goto fail;
|
|
|
|
ff_thread_finish_setup(s->avctx);
|
|
|
|
return 0;
|
|
|
|
fail:
|
|
if (s->ref)
|
|
ff_hevc_unref_frame(s, s->ref, ~0);
|
|
s->ref = NULL;
|
|
return ret;
|
|
}
|
|
|
|
static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal)
|
|
{
|
|
HEVCLocalContext *lc = &s->HEVClc;
|
|
GetBitContext *gb = &lc->gb;
|
|
int ctb_addr_ts, ret;
|
|
|
|
*gb = nal->gb;
|
|
s->nal_unit_type = nal->type;
|
|
s->temporal_id = nal->temporal_id;
|
|
|
|
switch (s->nal_unit_type) {
|
|
case HEVC_NAL_VPS:
|
|
ret = ff_hevc_decode_nal_vps(gb, s->avctx, &s->ps);
|
|
if (ret < 0)
|
|
goto fail;
|
|
break;
|
|
case HEVC_NAL_SPS:
|
|
ret = ff_hevc_decode_nal_sps(gb, s->avctx, &s->ps,
|
|
s->apply_defdispwin);
|
|
if (ret < 0)
|
|
goto fail;
|
|
break;
|
|
case HEVC_NAL_PPS:
|
|
ret = ff_hevc_decode_nal_pps(gb, s->avctx, &s->ps);
|
|
if (ret < 0)
|
|
goto fail;
|
|
break;
|
|
case HEVC_NAL_SEI_PREFIX:
|
|
case HEVC_NAL_SEI_SUFFIX:
|
|
ret = ff_hevc_decode_nal_sei(gb, s->avctx, &s->sei,
|
|
s->nal_unit_type);
|
|
if (ret < 0)
|
|
goto fail;
|
|
break;
|
|
case HEVC_NAL_TRAIL_R:
|
|
case HEVC_NAL_TRAIL_N:
|
|
case HEVC_NAL_TSA_N:
|
|
case HEVC_NAL_TSA_R:
|
|
case HEVC_NAL_STSA_N:
|
|
case HEVC_NAL_STSA_R:
|
|
case HEVC_NAL_BLA_W_LP:
|
|
case HEVC_NAL_BLA_W_RADL:
|
|
case HEVC_NAL_BLA_N_LP:
|
|
case HEVC_NAL_IDR_W_RADL:
|
|
case HEVC_NAL_IDR_N_LP:
|
|
case HEVC_NAL_CRA_NUT:
|
|
case HEVC_NAL_RADL_N:
|
|
case HEVC_NAL_RADL_R:
|
|
case HEVC_NAL_RASL_N:
|
|
case HEVC_NAL_RASL_R:
|
|
ret = hls_slice_header(s);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (s->max_ra == INT_MAX) {
|
|
if (s->nal_unit_type == HEVC_NAL_CRA_NUT || IS_BLA(s)) {
|
|
s->max_ra = s->poc;
|
|
} else {
|
|
if (IS_IDR(s))
|
|
s->max_ra = INT_MIN;
|
|
}
|
|
}
|
|
|
|
if ((s->nal_unit_type == HEVC_NAL_RASL_R || s->nal_unit_type == HEVC_NAL_RASL_N) &&
|
|
s->poc <= s->max_ra) {
|
|
s->is_decoded = 0;
|
|
break;
|
|
} else {
|
|
if (s->nal_unit_type == HEVC_NAL_RASL_R && s->poc > s->max_ra)
|
|
s->max_ra = INT_MIN;
|
|
}
|
|
|
|
if (s->sh.first_slice_in_pic_flag) {
|
|
ret = hevc_frame_start(s);
|
|
if (ret < 0)
|
|
return ret;
|
|
} else if (!s->ref) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "First slice in a frame missing.\n");
|
|
goto fail;
|
|
}
|
|
|
|
if (s->nal_unit_type != s->first_nal_type) {
|
|
av_log(s->avctx, AV_LOG_ERROR,
|
|
"Non-matching NAL types of the VCL NALUs: %d %d\n",
|
|
s->first_nal_type, s->nal_unit_type);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
if (!s->sh.dependent_slice_segment_flag &&
|
|
s->sh.slice_type != HEVC_SLICE_I) {
|
|
ret = ff_hevc_slice_rpl(s);
|
|
if (ret < 0) {
|
|
av_log(s->avctx, AV_LOG_WARNING,
|
|
"Error constructing the reference lists for the current slice.\n");
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
if (s->sh.first_slice_in_pic_flag && s->avctx->hwaccel) {
|
|
ret = s->avctx->hwaccel->start_frame(s->avctx, NULL, 0);
|
|
if (ret < 0)
|
|
goto fail;
|
|
}
|
|
|
|
if (s->avctx->hwaccel) {
|
|
ret = s->avctx->hwaccel->decode_slice(s->avctx, nal->raw_data, nal->raw_size);
|
|
if (ret < 0)
|
|
goto fail;
|
|
} else {
|
|
ctb_addr_ts = hls_slice_data(s);
|
|
if (ctb_addr_ts >= (s->ps.sps->ctb_width * s->ps.sps->ctb_height)) {
|
|
s->is_decoded = 1;
|
|
if ((s->ps.pps->transquant_bypass_enable_flag ||
|
|
(s->ps.sps->pcm.loop_filter_disable_flag && s->ps.sps->pcm_enabled_flag)) &&
|
|
s->ps.sps->sao_enabled)
|
|
restore_tqb_pixels(s);
|
|
}
|
|
|
|
if (ctb_addr_ts < 0) {
|
|
ret = ctb_addr_ts;
|
|
goto fail;
|
|
}
|
|
}
|
|
break;
|
|
case HEVC_NAL_EOS_NUT:
|
|
case HEVC_NAL_EOB_NUT:
|
|
s->seq_decode = (s->seq_decode + 1) & 0xff;
|
|
s->max_ra = INT_MAX;
|
|
break;
|
|
case HEVC_NAL_AUD:
|
|
case HEVC_NAL_FD_NUT:
|
|
break;
|
|
default:
|
|
av_log(s->avctx, AV_LOG_INFO,
|
|
"Skipping NAL unit %d\n", s->nal_unit_type);
|
|
}
|
|
|
|
return 0;
|
|
fail:
|
|
if (s->avctx->err_recognition & AV_EF_EXPLODE)
|
|
return ret;
|
|
return 0;
|
|
}
|
|
|
|
static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
|
|
{
|
|
int i, ret = 0;
|
|
|
|
s->ref = NULL;
|
|
s->eos = 0;
|
|
|
|
/* split the input packet into NAL units, so we know the upper bound on the
|
|
* number of slices in the frame */
|
|
ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx, s->is_nalff,
|
|
s->nal_length_size, s->avctx->codec_id);
|
|
if (ret < 0) {
|
|
av_log(s->avctx, AV_LOG_ERROR,
|
|
"Error splitting the input into NAL units.\n");
|
|
return ret;
|
|
}
|
|
|
|
for (i = 0; i < s->pkt.nb_nals; i++) {
|
|
if (s->pkt.nals[i].type == HEVC_NAL_EOB_NUT ||
|
|
s->pkt.nals[i].type == HEVC_NAL_EOS_NUT)
|
|
s->eos = 1;
|
|
}
|
|
|
|
/* decode the NAL units */
|
|
for (i = 0; i < s->pkt.nb_nals; i++) {
|
|
ret = decode_nal_unit(s, &s->pkt.nals[i]);
|
|
if (ret < 0) {
|
|
av_log(s->avctx, AV_LOG_WARNING,
|
|
"Error parsing NAL unit #%d.\n", i);
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
fail:
|
|
if (s->ref)
|
|
ff_thread_report_progress(&s->ref->tf, INT_MAX, 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void print_md5(void *log_ctx, int level, uint8_t md5[16])
|
|
{
|
|
int i;
|
|
for (i = 0; i < 16; i++)
|
|
av_log(log_ctx, level, "%02"PRIx8, md5[i]);
|
|
}
|
|
|
|
static int verify_md5(HEVCContext *s, AVFrame *frame)
|
|
{
|
|
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
|
|
int pixel_shift;
|
|
int i, j;
|
|
|
|
if (!desc)
|
|
return AVERROR(EINVAL);
|
|
|
|
pixel_shift = desc->comp[0].depth > 8;
|
|
|
|
av_log(s->avctx, AV_LOG_DEBUG, "Verifying checksum for frame with POC %d: ",
|
|
s->poc);
|
|
|
|
/* the checksums are LE, so we have to byteswap for >8bpp formats
|
|
* on BE arches */
|
|
#if HAVE_BIGENDIAN
|
|
if (pixel_shift && !s->checksum_buf) {
|
|
av_fast_malloc(&s->checksum_buf, &s->checksum_buf_size,
|
|
FFMAX3(frame->linesize[0], frame->linesize[1],
|
|
frame->linesize[2]));
|
|
if (!s->checksum_buf)
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
#endif
|
|
|
|
for (i = 0; frame->data[i]; i++) {
|
|
int width = s->avctx->coded_width;
|
|
int height = s->avctx->coded_height;
|
|
int w = (i == 1 || i == 2) ? (width >> desc->log2_chroma_w) : width;
|
|
int h = (i == 1 || i == 2) ? (height >> desc->log2_chroma_h) : height;
|
|
uint8_t md5[16];
|
|
|
|
av_md5_init(s->md5_ctx);
|
|
for (j = 0; j < h; j++) {
|
|
const uint8_t *src = frame->data[i] + j * frame->linesize[i];
|
|
#if HAVE_BIGENDIAN
|
|
if (pixel_shift) {
|
|
s->bdsp.bswap16_buf((uint16_t *) s->checksum_buf,
|
|
(const uint16_t *) src, w);
|
|
src = s->checksum_buf;
|
|
}
|
|
#endif
|
|
av_md5_update(s->md5_ctx, src, w << pixel_shift);
|
|
}
|
|
av_md5_final(s->md5_ctx, md5);
|
|
|
|
if (!memcmp(md5, s->sei.picture_hash.md5[i], 16)) {
|
|
av_log (s->avctx, AV_LOG_DEBUG, "plane %d - correct ", i);
|
|
print_md5(s->avctx, AV_LOG_DEBUG, md5);
|
|
av_log (s->avctx, AV_LOG_DEBUG, "; ");
|
|
} else {
|
|
av_log (s->avctx, AV_LOG_ERROR, "mismatching checksum of plane %d - ", i);
|
|
print_md5(s->avctx, AV_LOG_ERROR, md5);
|
|
av_log (s->avctx, AV_LOG_ERROR, " != ");
|
|
print_md5(s->avctx, AV_LOG_ERROR, s->sei.picture_hash.md5[i]);
|
|
av_log (s->avctx, AV_LOG_ERROR, "\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
}
|
|
|
|
av_log(s->avctx, AV_LOG_DEBUG, "\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hevc_decode_extradata(HEVCContext *s, uint8_t *buf, int length)
|
|
{
|
|
AVCodecContext *avctx = s->avctx;
|
|
GetByteContext gb;
|
|
int ret, i;
|
|
|
|
bytestream2_init(&gb, buf, length);
|
|
|
|
if (length > 3 && (buf[0] || buf[1] || buf[2] > 1)) {
|
|
/* It seems the extradata is encoded as hvcC format.
|
|
* Temporarily, we support configurationVersion==0 until 14496-15 3rd
|
|
* is finalized. When finalized, configurationVersion will be 1 and we
|
|
* can recognize hvcC by checking if avctx->extradata[0]==1 or not. */
|
|
int i, j, num_arrays, nal_len_size;
|
|
|
|
s->is_nalff = 1;
|
|
|
|
bytestream2_skip(&gb, 21);
|
|
nal_len_size = (bytestream2_get_byte(&gb) & 3) + 1;
|
|
num_arrays = bytestream2_get_byte(&gb);
|
|
|
|
/* nal units in the hvcC always have length coded with 2 bytes,
|
|
* so put a fake nal_length_size = 2 while parsing them */
|
|
s->nal_length_size = 2;
|
|
|
|
/* Decode nal units from hvcC. */
|
|
for (i = 0; i < num_arrays; i++) {
|
|
int type = bytestream2_get_byte(&gb) & 0x3f;
|
|
int cnt = bytestream2_get_be16(&gb);
|
|
|
|
for (j = 0; j < cnt; j++) {
|
|
// +2 for the nal size field
|
|
int nalsize = bytestream2_peek_be16(&gb) + 2;
|
|
if (bytestream2_get_bytes_left(&gb) < nalsize) {
|
|
av_log(s->avctx, AV_LOG_ERROR,
|
|
"Invalid NAL unit size in extradata.\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
ret = decode_nal_units(s, gb.buffer, nalsize);
|
|
if (ret < 0) {
|
|
av_log(avctx, AV_LOG_ERROR,
|
|
"Decoding nal unit %d %d from hvcC failed\n",
|
|
type, i);
|
|
return ret;
|
|
}
|
|
bytestream2_skip(&gb, nalsize);
|
|
}
|
|
}
|
|
|
|
/* Now store right nal length size, that will be used to parse
|
|
* all other nals */
|
|
s->nal_length_size = nal_len_size;
|
|
} else {
|
|
s->is_nalff = 0;
|
|
ret = decode_nal_units(s, buf, length);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
/* export stream parameters from the first SPS */
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) {
|
|
if (s->ps.sps_list[i]) {
|
|
const HEVCSPS *sps = (const HEVCSPS*)s->ps.sps_list[i]->data;
|
|
export_stream_params(s->avctx, &s->ps, sps);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output,
|
|
AVPacket *avpkt)
|
|
{
|
|
int ret;
|
|
int new_extradata_size;
|
|
uint8_t *new_extradata;
|
|
HEVCContext *s = avctx->priv_data;
|
|
|
|
if (!avpkt->size) {
|
|
ret = ff_hevc_output_frame(s, data, 1);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
*got_output = ret;
|
|
return 0;
|
|
}
|
|
|
|
new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA,
|
|
&new_extradata_size);
|
|
if (new_extradata && new_extradata_size > 0) {
|
|
ret = hevc_decode_extradata(s, new_extradata, new_extradata_size);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
s->ref = NULL;
|
|
ret = decode_nal_units(s, avpkt->data, avpkt->size);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (avctx->hwaccel) {
|
|
if (s->ref && avctx->hwaccel->end_frame(avctx) < 0)
|
|
av_log(avctx, AV_LOG_ERROR,
|
|
"hardware accelerator failed to decode picture\n");
|
|
} else {
|
|
/* verify the SEI checksum */
|
|
if (avctx->err_recognition & AV_EF_CRCCHECK && s->is_decoded &&
|
|
s->sei.picture_hash.is_md5) {
|
|
ret = verify_md5(s, s->ref->frame);
|
|
if (ret < 0 && avctx->err_recognition & AV_EF_EXPLODE) {
|
|
ff_hevc_unref_frame(s, s->ref, ~0);
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
s->sei.picture_hash.is_md5 = 0;
|
|
|
|
if (s->is_decoded) {
|
|
av_log(avctx, AV_LOG_DEBUG, "Decoded frame with POC %d.\n", s->poc);
|
|
s->is_decoded = 0;
|
|
}
|
|
|
|
if (s->output_frame->buf[0]) {
|
|
av_frame_move_ref(data, s->output_frame);
|
|
*got_output = 1;
|
|
}
|
|
|
|
return avpkt->size;
|
|
}
|
|
|
|
static int hevc_ref_frame(HEVCContext *s, HEVCFrame *dst, HEVCFrame *src)
|
|
{
|
|
int ret = ff_thread_ref_frame(&dst->tf, &src->tf);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
dst->tab_mvf_buf = av_buffer_ref(src->tab_mvf_buf);
|
|
if (!dst->tab_mvf_buf)
|
|
goto fail;
|
|
dst->tab_mvf = src->tab_mvf;
|
|
|
|
dst->rpl_tab_buf = av_buffer_ref(src->rpl_tab_buf);
|
|
if (!dst->rpl_tab_buf)
|
|
goto fail;
|
|
dst->rpl_tab = src->rpl_tab;
|
|
|
|
dst->rpl_buf = av_buffer_ref(src->rpl_buf);
|
|
if (!dst->rpl_buf)
|
|
goto fail;
|
|
|
|
dst->poc = src->poc;
|
|
dst->ctb_count = src->ctb_count;
|
|
dst->flags = src->flags;
|
|
dst->sequence = src->sequence;
|
|
|
|
if (src->hwaccel_picture_private) {
|
|
dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf);
|
|
if (!dst->hwaccel_priv_buf)
|
|
goto fail;
|
|
dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data;
|
|
}
|
|
|
|
return 0;
|
|
fail:
|
|
ff_hevc_unref_frame(s, dst, ~0);
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
|
|
static av_cold int hevc_decode_free(AVCodecContext *avctx)
|
|
{
|
|
HEVCContext *s = avctx->priv_data;
|
|
int i;
|
|
|
|
pic_arrays_free(s);
|
|
|
|
av_freep(&s->md5_ctx);
|
|
|
|
av_frame_free(&s->tmp_frame);
|
|
av_frame_free(&s->output_frame);
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
|
|
ff_hevc_unref_frame(s, &s->DPB[i], ~0);
|
|
av_frame_free(&s->DPB[i].frame);
|
|
}
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++)
|
|
av_buffer_unref(&s->ps.vps_list[i]);
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++)
|
|
av_buffer_unref(&s->ps.sps_list[i]);
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++)
|
|
av_buffer_unref(&s->ps.pps_list[i]);
|
|
|
|
ff_h2645_packet_uninit(&s->pkt);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static av_cold int hevc_init_context(AVCodecContext *avctx)
|
|
{
|
|
HEVCContext *s = avctx->priv_data;
|
|
int i;
|
|
|
|
s->avctx = avctx;
|
|
|
|
s->tmp_frame = av_frame_alloc();
|
|
if (!s->tmp_frame)
|
|
goto fail;
|
|
|
|
s->output_frame = av_frame_alloc();
|
|
if (!s->output_frame)
|
|
goto fail;
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
|
|
s->DPB[i].frame = av_frame_alloc();
|
|
if (!s->DPB[i].frame)
|
|
goto fail;
|
|
s->DPB[i].tf.f = s->DPB[i].frame;
|
|
}
|
|
|
|
s->max_ra = INT_MAX;
|
|
|
|
s->md5_ctx = av_md5_alloc();
|
|
if (!s->md5_ctx)
|
|
goto fail;
|
|
|
|
ff_bswapdsp_init(&s->bdsp);
|
|
|
|
s->context_initialized = 1;
|
|
|
|
return 0;
|
|
|
|
fail:
|
|
hevc_decode_free(avctx);
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
|
|
static int hevc_update_thread_context(AVCodecContext *dst,
|
|
const AVCodecContext *src)
|
|
{
|
|
HEVCContext *s = dst->priv_data;
|
|
HEVCContext *s0 = src->priv_data;
|
|
int i, ret;
|
|
|
|
if (!s->context_initialized) {
|
|
ret = hevc_init_context(dst);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
|
|
ff_hevc_unref_frame(s, &s->DPB[i], ~0);
|
|
if (s0->DPB[i].frame->buf[0]) {
|
|
ret = hevc_ref_frame(s, &s->DPB[i], &s0->DPB[i]);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++) {
|
|
av_buffer_unref(&s->ps.vps_list[i]);
|
|
if (s0->ps.vps_list[i]) {
|
|
s->ps.vps_list[i] = av_buffer_ref(s0->ps.vps_list[i]);
|
|
if (!s->ps.vps_list[i])
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) {
|
|
av_buffer_unref(&s->ps.sps_list[i]);
|
|
if (s0->ps.sps_list[i]) {
|
|
s->ps.sps_list[i] = av_buffer_ref(s0->ps.sps_list[i]);
|
|
if (!s->ps.sps_list[i])
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++) {
|
|
av_buffer_unref(&s->ps.pps_list[i]);
|
|
if (s0->ps.pps_list[i]) {
|
|
s->ps.pps_list[i] = av_buffer_ref(s0->ps.pps_list[i]);
|
|
if (!s->ps.pps_list[i])
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
}
|
|
|
|
if (s->ps.sps != s0->ps.sps)
|
|
ret = set_sps(s, s0->ps.sps, src->pix_fmt);
|
|
|
|
s->seq_decode = s0->seq_decode;
|
|
s->seq_output = s0->seq_output;
|
|
s->pocTid0 = s0->pocTid0;
|
|
s->max_ra = s0->max_ra;
|
|
|
|
s->is_nalff = s0->is_nalff;
|
|
s->nal_length_size = s0->nal_length_size;
|
|
|
|
if (s0->eos) {
|
|
s->seq_decode = (s->seq_decode + 1) & 0xff;
|
|
s->max_ra = INT_MAX;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static av_cold int hevc_decode_init(AVCodecContext *avctx)
|
|
{
|
|
HEVCContext *s = avctx->priv_data;
|
|
int ret;
|
|
|
|
avctx->internal->allocate_progress = 1;
|
|
|
|
ret = hevc_init_context(avctx);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (avctx->extradata_size > 0 && avctx->extradata) {
|
|
ret = hevc_decode_extradata(s, avctx->extradata, avctx->extradata_size);
|
|
if (ret < 0) {
|
|
hevc_decode_free(avctx);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static av_cold int hevc_init_thread_copy(AVCodecContext *avctx)
|
|
{
|
|
HEVCContext *s = avctx->priv_data;
|
|
int ret;
|
|
|
|
memset(s, 0, sizeof(*s));
|
|
|
|
ret = hevc_init_context(avctx);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void hevc_decode_flush(AVCodecContext *avctx)
|
|
{
|
|
HEVCContext *s = avctx->priv_data;
|
|
ff_hevc_flush_dpb(s);
|
|
s->max_ra = INT_MAX;
|
|
}
|
|
|
|
#define OFFSET(x) offsetof(HEVCContext, x)
|
|
#define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
|
|
|
|
static const AVOption options[] = {
|
|
{ "apply_defdispwin", "Apply default display window from VUI", OFFSET(apply_defdispwin),
|
|
AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, PAR },
|
|
{ NULL },
|
|
};
|
|
|
|
static const AVClass hevc_decoder_class = {
|
|
.class_name = "HEVC decoder",
|
|
.item_name = av_default_item_name,
|
|
.option = options,
|
|
.version = LIBAVUTIL_VERSION_INT,
|
|
};
|
|
|
|
AVCodec ff_hevc_decoder = {
|
|
.name = "hevc",
|
|
.long_name = NULL_IF_CONFIG_SMALL("HEVC (High Efficiency Video Coding)"),
|
|
.type = AVMEDIA_TYPE_VIDEO,
|
|
.id = AV_CODEC_ID_HEVC,
|
|
.priv_data_size = sizeof(HEVCContext),
|
|
.priv_class = &hevc_decoder_class,
|
|
.init = hevc_decode_init,
|
|
.close = hevc_decode_free,
|
|
.decode = hevc_decode_frame,
|
|
.flush = hevc_decode_flush,
|
|
.update_thread_context = hevc_update_thread_context,
|
|
.init_thread_copy = hevc_init_thread_copy,
|
|
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
|
|
AV_CODEC_CAP_FRAME_THREADS,
|
|
.profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles),
|
|
.caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING | FF_CODEC_CAP_INIT_THREADSAFE,
|
|
};
|