#include "bswapdsp.h"
#include "bytestream.h"
#include "cabac_functions.h"
-#include "golomb.h"
+#include "golomb_legacy.h"
#include "hevc.h"
#include "hevc_data.h"
#include "hevcdec.h"
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->output_width;
- avctx->height = sps->output_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;
num, den, 1 << 30);
}
-static int set_sps(HEVCContext *s, const HEVCSPS *sps)
+static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
{
- #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + CONFIG_HEVC_D3D11VA_HWACCEL + CONFIG_HEVC_VDPAU_HWACCEL)
+ #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;
- 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);
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_D3D11VA_HWACCEL
- *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
-#endif
#if CONFIG_HEVC_VDPAU_HWACCEL
*fmt++ = AV_PIX_FMT_VDPAU;
#endif
*fmt++ = sps->pix_fmt;
*fmt = AV_PIX_FMT_NONE;
- ret = ff_get_format(s->avctx, pix_fmts);
+ 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;
- s->avctx->pix_fmt = ret;
+
+ 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);
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) {
- 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);
- ret = set_sps(s, s->ps.sps);
+
+ 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;
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)];
- DECLARE_ALIGNED(32, int16_t, coeffs[MAX_TB_SIZE * MAX_TB_SIZE]) = { 0 };
- DECLARE_ALIGNED(8, uint8_t, significant_coeff_group_flag[8][8]) = { { 0 } };
+ 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;
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[] = {
trans_coeff_level = 1 + coeff_abs_level_greater1_flag[n];
if (trans_coeff_level == ((m < 8) ?
((n == first_greater1_coeff_idx) ? 3 : 2) : 1)) {
- int last_coeff_abs_level_remaining = ff_hevc_coeff_abs_level_remaining(s, trans_coeff_level, c_rice_param);
-
- trans_coeff_level += last_coeff_abs_level_remaining;
+ 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 (current_mv.pred_flag[0] && !current_mv.pred_flag[1]) {
- DECLARE_ALIGNED(16, int16_t, tmp[MAX_PB_SIZE * MAX_PB_SIZE]);
- DECLARE_ALIGNED(16, int16_t, tmp2[MAX_PB_SIZE * MAX_PB_SIZE]);
+ 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);
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]) {
- DECLARE_ALIGNED(16, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]);
- DECLARE_ALIGNED(16, int16_t, tmp2[MAX_PB_SIZE * MAX_PB_SIZE]);
+ 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);
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]) {
- DECLARE_ALIGNED(16, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]);
- DECLARE_ALIGNED(16, int16_t, tmp2[MAX_PB_SIZE * MAX_PB_SIZE]);
- DECLARE_ALIGNED(16, int16_t, tmp3[MAX_PB_SIZE * MAX_PB_SIZE]);
- DECLARE_ALIGNED(16, int16_t, tmp4[MAX_PB_SIZE * MAX_PB_SIZE]);
+ 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);
{
AVFrame *out = s->ref->frame;
- if (s->sei_frame_packing_present &&
- s->frame_packing_arrangement_type >= 3 &&
- s->frame_packing_arrangement_type <= 5 &&
- s->content_interpretation_type > 0 &&
- s->content_interpretation_type < 3) {
+ 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->frame_packing_arrangement_type) {
+ switch (s->sei.frame_packing.arrangement_type) {
case 3:
- if (s->quincunx_subsampling)
+ if (s->sei.frame_packing.quincunx_subsampling)
stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX;
else
stereo->type = AV_STEREO3D_SIDEBYSIDE;
break;
}
- if (s->content_interpretation_type == 2)
+ if (s->sei.frame_packing.content_interpretation_type == 2)
stereo->flags = AV_STEREO3D_FLAG_INVERT;
}
- if (s->sei_display_orientation_present &&
- (s->sei_anticlockwise_rotation || s->sei_hflip || s->sei_vflip)) {
- double angle = s->sei_anticlockwise_rotation * 360 / (double) (1 << 16);
+ 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);
av_display_rotation_set((int32_t *)rotation->data, angle);
av_display_matrix_flip((int32_t *)rotation->data,
- s->sei_hflip, s->sei_vflip);
+ s->sei.display_orientation.hflip,
+ s->sei.display_orientation.vflip);
+ }
+
+ if (s->sei.alternative_transfer.present &&
+ av_color_transfer_name(s->sei.alternative_transfer.preferred_transfer_characteristics) &&
+ s->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) {
+ s->avctx->color_trc = out->color_trc = s->sei.alternative_transfer.preferred_transfer_characteristics;
}
return 0;
break;
case HEVC_NAL_SEI_PREFIX:
case HEVC_NAL_SEI_SUFFIX:
- ret = ff_hevc_decode_nal_sei(s);
+ ret = ff_hevc_decode_nal_sei(gb, s->avctx, &s->sei,
+ s->nal_unit_type);
if (ret < 0)
goto fail;
break;
}
av_md5_final(s->md5_ctx, md5);
- if (!memcmp(md5, s->md5[i], 16)) {
+ 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, "; ");
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->md5[i]);
+ print_md5(s->avctx, AV_LOG_ERROR, s->sei.picture_hash.md5[i]);
av_log (s->avctx, AV_LOG_ERROR, "\n");
return AVERROR_INVALIDDATA;
}
return 0;
}
-static int hevc_decode_extradata(HEVCContext *s)
+static int hevc_decode_extradata(HEVCContext *s, uint8_t *buf, int length)
{
AVCodecContext *avctx = s->avctx;
GetByteContext gb;
int ret, i;
- bytestream2_init(&gb, avctx->extradata, avctx->extradata_size);
+ bytestream2_init(&gb, buf, length);
- if (avctx->extradata_size > 3 &&
- (avctx->extradata[0] || avctx->extradata[1] ||
- avctx->extradata[2] > 1)) {
+ 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
s->nal_length_size = nal_len_size;
} else {
s->is_nalff = 0;
- ret = decode_nal_units(s, avctx->extradata, avctx->extradata_size);
+ ret = decode_nal_units(s, buf, length);
if (ret < 0)
return ret;
}
AVPacket *avpkt)
{
int ret;
+ int new_extradata_size;
+ uint8_t *new_extradata;
HEVCContext *s = avctx->priv_data;
if (!avpkt->size) {
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)
} else {
/* verify the SEI checksum */
if (avctx->err_recognition & AV_EF_CRCCHECK && s->is_decoded &&
- s->is_md5) {
+ 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);
}
}
}
- s->is_md5 = 0;
+ 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);
dst->poc = src->poc;
dst->ctb_count = src->ctb_count;
- dst->window = src->window;
dst->flags = src->flags;
dst->sequence = src->sequence;
}
if (s->ps.sps != s0->ps.sps)
- ret = set_sps(s, 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;
return ret;
if (avctx->extradata_size > 0 && avctx->extradata) {
- ret = hevc_decode_extradata(s);
+ ret = hevc_decode_extradata(s, avctx->extradata, avctx->extradata_size);
if (ret < 0) {
hevc_decode_free(avctx);
return ret;
.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,
};