Any formatting/alignment/spacing change is skipped in this review, as it is possible to find a cleaned-up version in my repo.
On Sun, Aug 11, 2013 at 3:33 PM, Anton Khirnov <[email protected]> wrote: > > From: Guillaume Martres <[email protected]> > > > diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c > new file mode 100644 > index 0000000..5686bbf > --- /dev/null > +++ b/libavcodec/hevc.c > @@ -0,0 +1,2661 @@ [...] > +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_scan4x1_x[4] = { > + 0, 1, 2, 3, > +}; > + > +static const uint8_t diag_scan1x4_y[4] = { > + 0, 1, 2, 3, > +}; > + > +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_scan8x2_x[16] = { > + 0, 0, 1, 1, > + 2, 2, 3, 3, > + 4, 4, 5, 5, > + 6, 6, 7, 7, > +}; > + > +static const uint8_t diag_scan8x2_y[16] = { > + 0, 1, 0, 1, > + 0, 1, 0, 1, > + 0, 1, 0, 1, > + 0, 1, 0, 1, > +}; > + > + > +static const uint8_t diag_scan8x2_inv[2][8] = { > + { 0, 2, 4, 6, 8, 10, 12, 14, }, > + { 1, 3, 5, 7, 9, 11, 13, 15, }, > +}; > + > +static const uint8_t diag_scan2x8_x[16] = { > + 0, 0, 1, 0, > + 1, 0, 1, 0, > + 1, 0, 1, 0, > + 1, 0, 1, 1, > +}; > + > +static const uint8_t diag_scan2x8_y[16] = { > + 0, 1, 0, 2, > + 1, 3, 2, 4, > + 3, 5, 4, 6, > + 5, 7, 6, 7, > +}; > + > +static const uint8_t diag_scan2x8_inv[8][2] = { > + { 0, 2, }, > + { 1, 4, }, > + { 3, 6, }, > + { 5, 8, }, > + { 7, 10, }, > + { 9, 12, }, > + { 11, 14, }, > + { 13, 15, }, > +}; > + > +static const uint8_t diag_scan4x4_x[16] = { > + 0, 0, 1, 0, > + 1, 2, 0, 1, > + 2, 3, 1, 2, > + 3, 2, 3, 3, > +}; > + > +static const uint8_t diag_scan4x4_y[16] = { > + 0, 1, 0, 2, > + 1, 0, 3, 2, > + 1, 0, 3, 2, > + 1, 3, 2, 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_x[64] = { > + 0, 0, 1, 0, > + 1, 2, 0, 1, > + 2, 3, 0, 1, > + 2, 3, 4, 0, > + 1, 2, 3, 4, > + 5, 0, 1, 2, > + 3, 4, 5, 6, > + 0, 1, 2, 3, > + 4, 5, 6, 7, > + 1, 2, 3, 4, > + 5, 6, 7, 2, > + 3, 4, 5, 6, > + 7, 3, 4, 5, > + 6, 7, 4, 5, > + 6, 7, 5, 6, > + 7, 6, 7, 7, > +}; > + > +static const uint8_t diag_scan8x8_y[64] = { > + 0, 1, 0, 2, > + 1, 0, 3, 2, > + 1, 0, 4, 3, > + 2, 1, 0, 5, > + 4, 3, 2, 1, > + 0, 6, 5, 4, > + 3, 2, 1, 0, > + 7, 6, 5, 4, > + 3, 2, 1, 0, > + 7, 6, 5, 4, > + 3, 2, 1, 7, > + 6, 5, 4, 3, > + 2, 7, 6, 5, > + 4, 3, 7, 6, > + 5, 4, 7, 6, > + 5, 7, 6, 7, > +}; > + > +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, }, > +}; > + I'm not sure what is the situation in the other decoders, but could this be maybe moved in a header like hevc_tables.h? > +/** > + * NOTE: Each function hls_foo correspond to the function foo in the > + * specification (HLS stands for High Level Syntax). > + */ > + > +/** > + * Section 5.7 > + */ > +#define WPP1 What's this? > +static int pic_arrays_init(HEVCContext *s) > +{ > + int i; > + HEVCSharedContext *sc = s->HEVCsc; > + int pic_size = sc->sps->pic_width_in_luma_samples * > sc->sps->pic_height_in_luma_samples; > + int pic_size_in_ctb = pic_size >> (sc->sps->log2_min_coding_block_size > << 1); > + int ctb_count = sc->sps->pic_width_in_ctbs * sc->sps->pic_height_in_ctbs; > + int pic_width_in_min_pu = s->HEVCsc->sps->pic_width_in_luma_samples >> > s->HEVCsc->sps->log2_min_pu_size; > + int pic_height_in_min_pu = s->HEVCsc->sps->pic_height_in_luma_samples >> > s->HEVCsc->sps->log2_min_pu_size; > + sc->bs_width = sc->sps->pic_width_in_luma_samples >> 3; > + sc->bs_height = sc->sps->pic_height_in_luma_samples >> 3; > + sc->sao = av_mallocz(ctb_count * sizeof(*sc->sao)); > + sc->deblock = av_mallocz(ctb_count * sizeof(DBParams)); > + sc->split_cu_flag = av_malloc(pic_size); > + if (!sc->sao || !sc->deblock || !sc->split_cu_flag) > + goto fail; Umh I think it'd be much better if the check was immediately after allocation. If you ran out of memory for the first one, asking for more is just seeking trouble. A few of those array might not be needed all the time, is it worth to move initialization before they are actually in use? > + > + sc->skip_flag = av_malloc(pic_size_in_ctb); > + sc->tab_ct_depth = av_malloc(sc->sps->pic_height_in_min_cbs * > sc->sps->pic_width_in_min_cbs); > + if (!sc->skip_flag || !sc->tab_ct_depth) > + goto fail; ditto > + > + sc->tab_ipm = av_malloc(pic_height_in_min_pu * pic_width_in_min_pu); > + if (!sc->tab_ipm) > + goto fail; > + > + sc->cbf_luma = av_malloc(pic_width_in_min_pu * pic_height_in_min_pu); > + sc->is_pcm = av_malloc(pic_width_in_min_pu * pic_height_in_min_pu); > + if (!sc->cbf_luma || !sc->is_pcm) > + goto fail; ditto > + > + sc->qp_y_tab = av_malloc(pic_size_in_ctb * sizeof(int8_t)); > + if (!sc->qp_y_tab) > + goto fail; > + > + for (i = 0; i < FF_ARRAY_ELEMS(sc->DPB); i++) { > + sc->DPB[i].tab_mvf = av_malloc(pic_width_in_min_pu * > + pic_height_in_min_pu * > + sizeof(*sc->DPB[i].tab_mvf)); > + if (!sc->DPB[i].tab_mvf) > + goto fail; > + sc->DPB[i].refPicListTab = av_mallocz(ctb_count * > sizeof(RefPicListTab**)); > + if (!sc->DPB[i].refPicListTab) > + goto fail; > + } > + > + sc->horizontal_bs = av_mallocz(2 * sc->bs_width * sc->bs_height); > + sc->vertical_bs = av_mallocz(2 * sc->bs_width * sc->bs_height); > + if (!sc->horizontal_bs || !sc->vertical_bs) > + goto fail; ditto > + return 0; > +fail: > + pic_arrays_free(s); > + return AVERROR(ENOMEM); > +} > + > +static int hls_slice_header(HEVCContext *s) > +{ > + int i, ret, j; > + GetBitContext *gb = s->HEVClc->gb; > + HEVCSharedContext *sc = s->HEVCsc; > + SliceHeader *sh = &sc->sh; > + int slice_address_length = 0; > + > + // initial values > + sh->beta_offset = 0; > + sh->tc_offset = 0; > + > + // Coded parameters > + sh->first_slice_in_pic_flag = get_bits1(gb); > + if ((sc->nal_unit_type == NAL_IDR_W_RADL || sc->nal_unit_type == > NAL_IDR_N_LP) && > + sh->first_slice_in_pic_flag) { > + sc->seq_decode = (sc->seq_decode + 1) & 0xff; > + } > + if (sc->nal_unit_type >= 16 && sc->nal_unit_type <= 23) > + sh->no_output_of_prior_pics_flag = get_bits1(gb); > + > + sh->pps_id = get_ue_golomb(gb); > + if (sh->pps_id >= MAX_PPS_COUNT || !sc->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; > + } > + sc->pps = sc->pps_list[sh->pps_id]; > + if (sc->sps != sc->sps_list[sc->pps->sps_id]) { > + const AVPixFmtDescriptor *desc; > + > + sc->sps = sc->sps_list[sc->pps->sps_id]; > + sc->vps = sc->vps_list[sc->sps->vps_id]; > + > + //TODO: Handle switching between different SPS better > + if (s->width != sc->sps->pic_width_in_luma_samples || > + s->height != sc->sps->pic_height_in_luma_samples) { > + pic_arrays_free(s); > + ret = pic_arrays_init(s); > + s->width = sc->sps->pic_width_in_luma_samples; > + s->height = sc->sps->pic_height_in_luma_samples; > + if (ret < 0) > + return AVERROR(ENOMEM); > + } > + s->avctx->width = sc->sps->pic_width_in_luma_samples; > + s->avctx->height = sc->sps->pic_height_in_luma_samples; Here be cropping (in my repo). > + if (sc->sps->chroma_format_idc == 0 || > sc->sps->separate_colour_plane_flag) { > + av_log(s->avctx, AV_LOG_ERROR, > + "TODO: sc->sps->chroma_format_idc == 0 || " > + "sc->sps->separate_colour_plane_flag\n"); May I suggest to split the error check and a friendlier text error? Something like "TODO: unsupported colorspace" for the first and "TODO: only planar colorspaces are supported" for the second. > + return AVERROR_PATCHWELCOME; > + } > + > + if (sc->sps->chroma_format_idc == 1) { > + switch (sc->sps->bit_depth) { > + case 8: > + s->avctx->pix_fmt = PIX_FMT_YUV420P; > + break; > + case 9: > + s->avctx->pix_fmt = PIX_FMT_YUV420P9; > + break; > + case 10: > + s->avctx->pix_fmt = PIX_FMT_YUV420P10; > + break; > + } Should the default case error out with "unsupported bit depth"? > + } else { > + av_log(s->avctx, AV_LOG_ERROR, "non-4:2:0 support is currently > unspecified.\n"); > + return AVERROR_PATCHWELCOME; > + } > + > + desc = av_pix_fmt_desc_get(s->avctx->pix_fmt); > + if (!desc) > + return AVERROR(EINVAL); > + > + sc->sps->hshift[0] = sc->sps->vshift[0] = 0; nit: return after ther first '=' like below > + sc->sps->hshift[2] = > + sc->sps->hshift[1] = desc->log2_chroma_w; > + sc->sps->vshift[2] = > + sc->sps->vshift[1] = desc->log2_chroma_h; > + > + sc->sps->pixel_shift = sc->sps->bit_depth > 8; > + > + ff_hevc_pred_init(&sc->hpc, sc->sps->bit_depth); > + ff_hevc_dsp_init(&sc->hevcdsp, sc->sps->bit_depth); > + ff_videodsp_init(&sc->vdsp, sc->sps->bit_depth); > + } [...] > + if (sh->num_entry_point_offsets > 0) { > + int offset_len = get_ue_golomb(gb) + 1; > + int segments = offset_len >> 4; > + int rest = (offset_len & 15); > + av_freep(&sh->entry_point_offset); > + av_freep(&sh->offset); > + av_freep(&sh->size); > + sh->entry_point_offset = av_malloc(sh->num_entry_point_offsets * > sizeof(int)); > + sh->offset = av_malloc(sh->num_entry_point_offsets * > sizeof(int)); > + sh->size = av_malloc(sh->num_entry_point_offsets * sizeof(int)); unchecked allocations > + for (i = 0; i < sh->num_entry_point_offsets; i++) { > + int val = 0; > + for (j = 0; j < segments; j++) { > + val <<= 16; > + val += get_bits(gb, 16); > + } > + if (rest) { > + val <<= rest; > + val += get_bits(gb, rest); > + } > + sh->entry_point_offset[i] = val + 1; // +1; // +1 to get the > size nit: clean the second +1; > + } > + if (s->threads_number > 1 && (sc->pps->num_tile_rows > 1 || > sc->pps->num_tile_columns > 1)) > + sc->enable_parallel_tiles = 1; > + else > + sc->enable_parallel_tiles = 0; > + } else > + sc->enable_parallel_tiles = 0; > + } > + > + if (sc->pps->slice_header_extension_present_flag) { > + int length = get_ue_golomb(gb); > + for (i = 0; i < length; i++) > + skip_bits(gb, 8); // slice_header_extension_data_byte > + } > + > + // Inferred parameters > + > + sh->slice_qp = 26 + sc->pps->pic_init_qp_minus26 + sh->slice_qp_delta; > + sh->slice_ctb_addr_rs = sh->slice_address; > + sh->slice_cb_addr_zs = sh->slice_address << > + (sc->sps->log2_diff_max_min_coding_block_size << > 1); > + > + return 0; > +} > + > +#define CTB(tab, x, y) ((tab)[(y) * sc->sps->pic_width_in_ctbs + (x)]) > + > +#define set_sao(elem, value) \ > + if (!sao_merge_up_flag && !sao_merge_left_flag) { \ > + sao->elem = value; \ > + } else if (sao_merge_left_flag) { \ > + sao->elem = CTB(sc->sao, rx-1, ry).elem; \ > + } else if (sao_merge_up_flag) { \ > + sao->elem = CTB(sc->sao, rx, ry-1).elem; \ > + } else { \ > + sao->elem = 0; \ > + } Please don't use a macro for this: I recommend a small private function which can be inlined at compiler choice. > + > +static int hls_sao_param(HEVCContext *s, int rx, int ry) > +{ > + > + int c_idx, i; > + int sao_merge_left_flag = 0; > + int sao_merge_up_flag = 0; > + HEVCSharedContext *sc = s->HEVCsc; > + HEVCLocalContext *lc = s->HEVClc; > + int shift = sc->sps->bit_depth - FFMIN(sc->sps->bit_depth, 10); > + > + SAOParams *sao = &CTB(sc->sao, rx, ry); > + > + 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 (!sc->sh.slice_sample_adaptive_offset_flag[c_idx]) > + 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; //avoid undefined values > + 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]; > + } > + } > + } > + return 0; > +} > + > +#undef set_sao > +#undef CTB > + > +static av_always_inline int min_cb_addr_zs(HEVCSharedContext *sc, int x, int > y) > +{ > + return sc->pps->min_cb_addr_zs[y * sc->sps->pic_width_in_min_cbs + x]; > +} > + > +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) Can this stay outside the function? > + HEVCSharedContext *sc = s->HEVCsc; > + HEVCLocalContext *lc = s->HEVClc; > + int i; > + > + 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 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 = sc->frame->linesize[c_idx]; > + int hshift = sc->sps->hshift[c_idx]; > + int vshift = sc->sps->vshift[c_idx]; > + uint8_t *dst = &sc->frame->data[c_idx][(y0 >> vshift) * stride + > + ((x0 >> hshift) << > sc->sps->pixel_shift)]; > + DECLARE_ALIGNED( 16, int16_t, coeffs[MAX_TB_SIZE * MAX_TB_SIZE] ) = {0}; > + > + int trafo_size = 1 << log2_trafo_size; > + > + memset(lc->rc.significant_coeff_group_flag, 0, 8 * 8); > + > + if (sc->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); > + } [...] > + > + if (lc->cu.cu_transquant_bypass_flag) { > + sc->hevcdsp.transquant_bypass[log2_trafo_size-2](dst, coeffs, > stride); > + } else { > + int qp; > + int qp_y = lc->qp_y; > + static int qp_c[] = { 29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, > 36, 37, 37 }; should this be const too? > + if (c_idx == 0) { > + qp = qp_y + sc->sps->qp_bd_offset; > + } else { > + int qp_i, offset; > + > + if (c_idx == 1) { > + offset = sc->pps->cb_qp_offset + sc->sh.slice_cb_qp_offset; > + } else { > + offset = sc->pps->cr_qp_offset + sc->sh.slice_cr_qp_offset; > + } > + qp_i = av_clip_c(qp_y + offset, - sc->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 += sc->sps->qp_bd_offset; > + > + } [...] > +static int decode_nal_unit(HEVCContext *s, const uint8_t *nal, int length) > +{ > + HEVCSharedContext *sc = s->HEVCsc; > + HEVCLocalContext *lc = s->HEVClc; > + GetBitContext *gb = lc->gb; > + > + int ctb_addr_ts; > + int ret; > + > + av_log(s->avctx, AV_LOG_DEBUG, "=================\n"); Is this needed anymore? > + > + ret = init_get_bits8(gb, nal, length); > + if (ret < 0) > + return ret; > + > + ret = hls_nal_unit(s); > + if (ret < 0) { > + av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n", > + sc->nal_unit_type); > + if (s->avctx->err_recognition & AV_EF_EXPLODE) { > + return ret; > + } > + return 0; > + } else if (!ret) > + return 0; > + > + switch (sc->nal_unit_type) { > + case NAL_VPS: > + ff_hevc_decode_nal_vps(s); > + break; > + case NAL_SPS: > + ff_hevc_decode_nal_sps(s); > + break; > + case NAL_PPS: > + ff_hevc_decode_nal_pps(s); > + break; > + case NAL_SEI_PREFIX: > + case NAL_SEI_SUFFIX: > + ff_hevc_decode_nal_sei(s); > + break; > + case NAL_TRAIL_R: > + case NAL_TRAIL_N: > + case NAL_TSA_N: > + case NAL_TSA_R: > + case NAL_STSA_N: > + case NAL_STSA_R: > + case NAL_BLA_W_LP: > + case NAL_BLA_W_RADL: > + case NAL_BLA_N_LP: > + case NAL_IDR_W_RADL: > + case NAL_IDR_N_LP: > + case NAL_CRA_NUT: > + case NAL_RADL_N: > + case NAL_RADL_R: > + case NAL_RASL_N: > + case NAL_RASL_R: > + ret = hls_slice_header(s); > + lc->isFirstQPgroup = !sc->sh.dependent_slice_segment_flag; > + > + if (ret < 0) > + if (ret == AVERROR_INVALIDDATA && !(s->avctx->err_recognition & > AV_EF_EXPLODE)) > + return 0; > + else > + return ret; Umh does this silent averror hijacking make sense in this context? Could this be moved further down the pipe where the invalid data is triggered? > + if (sc->max_ra == INT_MAX) { > + if (sc->nal_unit_type == NAL_CRA_NUT || > + sc->nal_unit_type == NAL_BLA_W_LP || > + sc->nal_unit_type == NAL_BLA_N_LP || > + sc->nal_unit_type == NAL_BLA_N_LP) { > + sc->max_ra = sc->poc; > + } else { > + if (sc->nal_unit_type == NAL_IDR_W_RADL || sc->nal_unit_type > == NAL_IDR_N_LP) > + sc->max_ra = INT_MIN; > + } > + } > + [...] > + > + s->avctx = avctx; > + s->HEVCsc = av_mallocz(sizeof(HEVCSharedContext)); > + s->HEVClc = av_mallocz(sizeof(HEVCLocalContext)); unchecked allocations > + memset(&s->HEVCsc->sh, 0, sizeof(s->HEVCsc->sh)); > + > + lc = s->HEVClcList[0] = s->HEVClc; > + sc = s->HEVCsc; > + s->sList[0] = s; > + > + lc->BufferMC = av_malloc((MAX_PB_SIZE + 7) * MAX_PB_SIZE * > sizeof(uint16_t)); > + sc->tmp_frame = av_frame_alloc(); > + sc->cabac_state = av_malloc(HEVC_CONTEXTS); > + > + lc->gb = av_malloc(sizeof(GetBitContext)); > + lc->cc = av_malloc(sizeof(CABACContext)); > + lc->cabac_state = av_malloc(HEVC_CONTEXTS); ditto > + lc->ctx_set = 0; > + lc->greater1_ctx = 0; > + lc->last_coeff_abs_level_greater1_flag = 0; > + if (!sc->tmp_frame) > + return AVERROR(ENOMEM); > + sc->max_ra = INT_MAX; > + for (i = 0; i < FF_ARRAY_ELEMS(sc->DPB); i++) { > + sc->DPB[i].frame = av_frame_alloc(); > + if (!sc->DPB[i].frame) > + return AVERROR(ENOMEM); > + } > + memset(sc->vps_list, 0, sizeof(sc->vps_list)); > + memset(sc->sps_list, 0, sizeof(sc->sps_list)); > + memset(sc->pps_list, 0, sizeof(sc->pps_list)); > + sc->ctb_entry_count = NULL; > + for (i = 0; i < MAX_TRANSFORM_DEPTH; i++) { > + lc->tt.cbf_cb[i] = av_malloc(MAX_CU_SIZE * MAX_CU_SIZE); > + lc->tt.cbf_cr[i] = av_malloc(MAX_CU_SIZE * MAX_CU_SIZE); ditto > + if (!lc->tt.cbf_cb[i] || !lc->tt.cbf_cr[i]) > + return AVERROR(ENOMEM); > + } > + sc->skipped_bytes_pos_size = 1024; // initial buffer size > + sc->skipped_bytes_pos = av_malloc_array(sc->skipped_bytes_pos_size, > sizeof(*sc->skipped_bytes_pos)); > + sc->enable_parallel_tiles = 0; > + //s->threads_number = avctx->thread_count; > + s->threads_number = 1; > + > + if (avctx->extradata_size > 0 && avctx->extradata) > + return decode_nal_units(s, s->avctx->extradata, > s->avctx->extradata_size); > + s->width = s->height = 0; should s->coded_width and s->coded_height be zeroed here too? > + > + return 0; > +} > + > diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h > new file mode 100644 > index 0000000..a22dfe6 > --- /dev/null > +++ b/libavcodec/hevc.h [...] > +typedef struct MvField { > + Mv mv[2]; > + int8_t ref_idx[2]; > + int8_t pred_flag[2]; > + uint8_t is_intra; > +} MvField; > + > +// MERGE > +#define MRG_MAX_NUM_CANDS 5 maybe this could be moved to libavcodec/hevc_mvs.c which is the only place where this is used > + > +typedef struct PredictionUnit { > + uint8_t merge_flag; > + int mpm_idx; > + int rem_intra_luma_pred_mode; > + uint8_t intra_pred_mode[4]; > + uint8_t intra_pred_mode_c; > + Mv mvd; > +} PredictionUnit; > + > +typedef struct TransformTree { > + uint8_t *cbf_cb[MAX_TRANSFORM_DEPTH]; > + uint8_t *cbf_cr[MAX_TRANSFORM_DEPTH]; > + uint8_t cbf_luma; > + > + // Inferred parameters > + uint8_t inter_split_flag; > +} TransformTree; > + > +typedef struct TransformUnit { > + int cu_qp_delta; > + > + // Inferred parameters; > + uint8_t is_cu_qp_delta_coded; > + int cur_intra_pred_mode; > +} TransformUnit; > + > +typedef struct ResidualCoding { > + uint8_t significant_coeff_group_flag[8][8]; > +} ResidualCoding; > + > +enum SAOType { > + SAO_NOT_APPLIED = 0, > + SAO_BAND, > + SAO_EDGE > +}; > + > +enum SAOEOClass { > + SAO_EO_HORIZ = 0, > + SAO_EO_VERT, > + SAO_EO_135D, > + SAO_EO_45D > +}; > + > +typedef struct SAOParams { > + uint8_t type_idx[3]; ///< sao_type_idx > + > + int offset_abs[3][4]; ///< sao_offset_abs > + int offset_sign[3][4]; ///< sao_offset_sign > + > + int band_position[3]; ///< sao_band_position > + > + int eo_class[3]; ///< sao_eo_class > + > + // Inferred parameters > + int offset_val[3][5]; ///<SaoOffsetVal > +} SAOParams; maybe the comments could be aligned > + > +typedef struct DBParams { > + uint8_t disable; > + int beta_offset; > + int tc_offset; > +} DBParams; > + > +#define HEVC_FRAME_FLAG_OUTPUT (1 << 0) > +#define HEVC_FRAME_FLAG_SHORT_REF (1 << 1) Isn't this just a convoluted way of saying 1 and 2? Plus this is used only in libavcodec/hevc_refs.c, so maybe it's better to put these defines there [...] > +typedef struct HEVCLocalContext { > + uint8_t *cabac_state; > + int ctx_set; > + int greater1_ctx; > + int last_coeff_abs_level_greater1_flag; > + int c_rice_param; > + int last_coeff_abs_level_remaining; > + GetBitContext *gb; // > + CABACContext *cc; // stray // or something is missing? > + TransformTree tt; > + TransformUnit tu; > + ResidualCoding rc; > + uint8_t isFirstQPgroup; > + int8_t qp_y; > + int8_t curr_qp_y; > + uint8_t ctb_left_flag; > + uint8_t ctb_up_flag; > + uint8_t ctb_up_right_flag; > + uint8_t ctb_up_left_flag; > + int start_of_tiles_x; > + int end_of_tiles_x; > + int end_of_tiles_y; > + uint8_t *edge_emu_buffer; > + CodingTree ct; > + CodingUnit cu; > + PredictionUnit pu; > + int16_t* BufferMC; > + Filter_data *save_boundary_strengths; > + int nb_saved; > +} HEVCLocalContext; > + > +typedef struct HEVCSharedContext { > + uint8_t *cabac_state; // ditto > + > + AVFrame *frame; > + AVFrame *sao_frame; > + AVFrame *tmp_frame; > + VPS *vps; > + SPS *sps; > + PPS *pps; > + VPS *vps_list[MAX_VPS_COUNT]; > + SPS *sps_list[MAX_SPS_COUNT]; > + PPS *pps_list[MAX_PPS_COUNT]; [...] > diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c > new file mode 100644 > index 0000000..f92025e > --- /dev/null > +++ b/libavcodec/hevc_cabac.c > @@ -0,0 +1,926 @@ [...] > +/** > + * Offset to ctxIdx 0 in init_values and states, indexed by SyntaxElement. > + */ > +static const int elem_offset[sizeof(num_bins_in_se)] = { > + 0, > + 1, > + 2, > + 2, > + 2, > + 2, > + 2, > + 2, > + 5, > + 6, > + 9, > + 12, > + 13, > + 17, > + 17, > + 18, > + 18, > + 18, > + 20, > + 21, > + 22, > + 27, > + 29, > + 31, > + 33, > + 35, > + 35, > + 35, > + 36, > + 37, > + 40, > + 42, > + 46, > + 48, > + 66, > + 84, > + 84, > + 84, > + 88, > + 130, > + 154, > + 160, > + 160,}; I think this is taking too much space, unless comments are added > + > +#define CNU 154 > +/** > + * Indexed by init_type > + */ > +static const uint8_t init_values[3][HEVC_CONTEXTS] = { > + { > + // sao_merge_flag > + 153, > + // sao_type_idx > + 200, > + // split_coding_unit_flag > + 139, 141, 157, > + // cu_transquant_bypass_flag > + 154, > + // skip_flag > + CNU, CNU, CNU, > + // cu_qp_delta > + 154, 154, 154, > + // pred_mode > + CNU, > + // part_mode > + 184, CNU, CNU, CNU, > + // prev_intra_luma_pred_mode > + 184, > + // intra_chroma_pred_mode > + 63, 139, > + // merge_flag > + CNU, > + // merge_idx > + CNU, > + // inter_pred_idc > + CNU, CNU, CNU, CNU, CNU, > + // ref_idx_l0 > + CNU, CNU, > + // ref_idx_l1 > + CNU, CNU, > + // abs_mvd_greater1_flag > + CNU, CNU, > + // abs_mvd_greater1_flag > + CNU, CNU, > + // mvp_lx_flag > + CNU, > + // no_residual_data_flag > + CNU, > + // split_transform_flag > + 153, 138, 138, > + // cbf_luma > + 111, 141, > + // cbf_cb, cbf_cr > + 94, 138, 182, 154, > + // transform_skip_flag > + 139, 139, > + // last_significant_coeff_x_prefix > + 110, 110, 124, 125, 140, 153, 125, 127, 140, 109, 111, 143, 127, 111, > + 79, 108, 123, 63, > + // last_significant_coeff_y_prefix > + 110, 110, 124, 125, 140, 153, 125, 127, 140, 109, 111, 143, 127, 111, > + 79, 108, 123, 63, > + // significant_coeff_group_flag > + 91, 171, 134, 141, > + // significant_coeff_flag > + 111, 111, 125, 110, 110, 94, 124, 108, 124, 107, 125, 141, 179, 153, > + 125, 107, 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 140, > + 139, 182, 182, 152, 136, 152, 136, 153, 136, 139, 111, 136, 139, 111, > + // coeff_abs_level_greater1_flag > + 140, 92, 137, 138, 140, 152, 138, 139, 153, 74, 149, 92, 139, 107, > + 122, 152, 140, 179, 166, 182, 140, 227, 122, 197, > + // coeff_abs_level_greater2_flag > + 138, 153, 136, 167, 152, 152, > + }, > + { > + // sao_merge_flag > + 153, > + // sao_type_idx > + 185, > + // split_coding_unit_flag > + 107, 139, 126, > + // cu_transquant_bypass_flag > + 154, > + // skip_flag > + 197, 185, 201, > + // cu_qp_delta > + 154, 154, 154, > + // pred_mode > + 149, > + // part_mode > + 154, 139, 154, 154, > + // prev_intra_luma_pred_mode > + 154, > + // intra_chroma_pred_mode > + 152, 139, > + // merge_flag > + 110, > + // merge_idx > + 122, > + // inter_pred_idc > + 95, 79, 63, 31, 31, > + // ref_idx_l0 > + 153, 153, > + // ref_idx_l1 > + 153, 153, > + // abs_mvd_greater1_flag > + 140, 198, > + // abs_mvd_greater1_flag > + 140, 198, > + // mvp_lx_flag > + 168, > + // no_residual_data_flag > + 79, > + // split_transform_flag > + 124, 138, 94, > + // cbf_luma > + 153, 111, > + // cbf_cb, cbf_cr > + 149, 107, 167, 154, > + // transform_skip_flag > + 139, 139, > + // last_significant_coeff_x_prefix > + 125, 110, 94, 110, 95, 79, 125, 111, 110, 78, 110, 111, 111, 95, > + 94, 108, 123, 108, > + // last_significant_coeff_y_prefix > + 125, 110, 94, 110, 95, 79, 125, 111, 110, 78, 110, 111, 111, 95, > + 94, 108, 123, 108, > + // significant_coeff_group_flag > + 121, 140, 61, 154, > + // significant_coeff_flag > + 155, 154, 139, 153, 139, 123, 123, 63, 153, 166, 183, 140, 136, 153, > + 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, > + 153, 123, 123, 107, 121, 107, 121, 167, 151, 183, 140, 151, 183, 140, > + // coeff_abs_level_greater1_flag > + 154, 196, 196, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, > + 136, 137, 169, 194, 166, 167, 154, 167, 137, 182, > + // coeff_abs_level_greater2_flag > + 107, 167, 91, 122, 107, 167, > + }, > + { > + // sao_merge_flag > + 153, > + // sao_type_idx > + 160, > + // split_coding_unit_flag > + 107, 139, 126, > + // cu_transquant_bypass_flag > + 154, > + // skip_flag > + 197, 185, 201, > + // cu_qp_delta > + 154, 154, 154, > + // pred_mode > + 134, > + // part_mode > + 154, 139, 154, 154, > + // prev_intra_luma_pred_mode > + 183, > + // intra_chroma_pred_mode > + 152, 139, > + // merge_flag > + 154, > + // merge_idx > + 137, > + // inter_pred_idc > + 95, 79, 63, 31, 31, > + // ref_idx_l0 > + 153, 153, > + // ref_idx_l1 > + 153, 153, > + // abs_mvd_greater1_flag > + 169, 198, > + // abs_mvd_greater1_flag > + 169, 198, > + // mvp_lx_flag > + 168, > + // no_residual_data_flag > + 79, > + // split_transform_flag > + 224, 167, 122, > + // cbf_luma > + 153, 111, > + // cbf_cb, cbf_cr > + 149, 92, 167, 154, > + // transform_skip_flag > + 139, 139, > + // last_significant_coeff_x_prefix > + 125, 110, 124, 110, 95, 94, 125, 111, 111, 79, 125, 126, 111, 111, > + 79, 108, 123, 93, > + // last_significant_coeff_y_prefix > + 125, 110, 124, 110, 95, 94, 125, 111, 111, 79, 125, 126, 111, 111, > + 79, 108, 123, 93, > + // significant_coeff_group_flag > + 121, 140, 61, 154, > + // significant_coeff_flag > + 170, 154, 139, 153, 139, 123, 123, 63, 124, 166, 183, 140, 136, 153, > + 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, > + 153, 138, 138, 122, 121, 122, 121, 167, 151, 183, 140, 151, 183, 140, > + // coeff_abs_level_greater1_flag > + 154, 196, 167, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, > + 136, 122, 169, 208, 166, 167, 154, 152, 167, 182, > + // coeff_abs_level_greater2_flag > + 107, 167, 91, 107, 107, 167, > + }, > +}; This table has some weid indentation and comment placement > + memcpy(s->HEVCsc->cabac_state, s->HEVClc->cabac_state, > HEVC_CONTEXTS); > + } > +} > + > +static void load_states(HEVCContext *s) > +{ > + memcpy(s->HEVClc->cabac_state, s->HEVCsc->cabac_state, HEVC_CONTEXTS); > +} I believe this load_states isn't worth a function on its own: I'd rather manually call the memcpy in the places where it is needed. > + > +static void cabac_reinit(HEVCLocalContext *lc) > +{ > + skip_bytes(lc->cc,0); > +} ditto > + > +static void cabac_init_decoder(HEVCContext *s) > +{ > + GetBitContext *gb = s->HEVClc->gb; > + skip_bits(gb, 1); > + align_get_bits(gb); [...] > diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c > new file mode 100644 > index 0000000..170a0c1 > --- /dev/null > +++ b/libavcodec/hevc_filter.c > @@ -0,0 +1,626 @@ Seems ok (after k&r). > diff --git a/libavcodec/hevc_mvs.c b/libavcodec/hevc_mvs.c > new file mode 100644 > index 0000000..5c7ef6a > --- /dev/null > +++ b/libavcodec/hevc_mvs.c > @@ -0,0 +1,1063 @@ I think Luca is taking care of this file. > diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c > new file mode 100644 > index 0000000..2a4699a > --- /dev/null > +++ b/libavcodec/hevc_parser.c > @@ -0,0 +1,125 @@ Seems ok (after k&r). > diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c > new file mode 100644 > index 0000000..9012076 > --- /dev/null > +++ b/libavcodec/hevc_ps.c > @@ -0,0 +1,959 @@ Seems ok (after k&r). > diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c > new file mode 100644 > index 0000000..a96e937 > --- /dev/null > +++ b/libavcodec/hevc_refs.c > @@ -0,0 +1,383 @@ Seems ok too (after k&r). > diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c > new file mode 100644 > index 0000000..5622b6e > --- /dev/null > +++ b/libavcodec/hevc_sei.c > @@ -0,0 +1,131 @@ > + > +static void decode_nal_sei_frame_packing_arrangement(HEVCLocalContext *lc) > +{ > + GetBitContext *gb = lc->gb; > + int cancel, type, quincunx; > + > + get_ue_golomb(gb); // frame_packing_arrangement_id > + cancel = get_bits1(gb); // frame_packing_cancel_flag > + if ( cancel == 0 ) > + { > + type = get_bits(gb, 7); // frame_packing_arrangement_type > + quincunx = get_bits1(gb); // quincunx_sampling_flag > + skip_bits(gb, 6); // content_interpretation_type > + > + // the following skips spatial_flipping_flag frame0_flipped_flag > + // field_views_flag current_frame_is_frame0_flag > + // frame0_self_contained_flag frame1_self_contained_flag > + skip_bits(gb, 6); > + > + if ( quincunx == 0 && type != 5 ) > + skip_bits(gb, 16); // frame[01]_grid_position_[xy] > + skip_bits(gb, 8); // > frame_packing_arrangement_reserved_byte > + skip_bits1(gb); // > frame_packing_arrangement_persistance_flag > + } > + skip_bits1(gb); // upsampled_aspect_ratio_flag > +} Maybe this SEI parsing could be commented out until the stereo3d transcoding patches get merged. > diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c > new file mode 100644 > index 0000000..b0b883c > --- /dev/null > +++ b/libavcodec/hevcdsp.c > @@ -0,0 +1,196 @@ > diff --git a/libavcodec/hevcdsp.h b/libavcodec/hevcdsp.h > new file mode 100644 > index 0000000..fdab250 > --- /dev/null > +++ b/libavcodec/hevcdsp.h > @@ -0,0 +1,79 @@ > diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c > new file mode 100644 > index 0000000..df12119 > --- /dev/null > +++ b/libavcodec/hevcdsp_template.c > @@ -0,0 +1,1384 @@ > diff --git a/libavcodec/hevcpred.c b/libavcodec/hevcpred.c > new file mode 100644 > index 0000000..5f76f1f > --- /dev/null > +++ b/libavcodec/hevcpred.c > @@ -0,0 +1,66 @@ > diff --git a/libavcodec/hevcpred.h b/libavcodec/hevcpred.h > new file mode 100644 > index 0000000..35340c5 > --- /dev/null > +++ b/libavcodec/hevcpred.h > @@ -0,0 +1,40 @@ > diff --git a/libavcodec/hevcpred_template.c b/libavcodec/hevcpred_template.c > new file mode 100644 > index 0000000..ade13c0 > --- /dev/null > +++ b/libavcodec/hevcpred_template.c > @@ -0,0 +1,718 @@ Sorry, not familiar with these files, skipping review. > diff --git a/libavformat/Makefile b/libavformat/Makefile > index 0b788c9..d2e9328 100644 > --- a/libavformat/Makefile > +++ b/libavformat/Makefile OK > diff --git a/libavformat/allformats.c b/libavformat/allformats.c > index 585cf43..3bdbadf 100644 > --- a/libavformat/allformats.c > +++ b/libavformat/allformats.c > @@ -117,6 +117,7 @@ void av_register_all(void) > REGISTER_MUXDEMUX(H261, h261); > REGISTER_MUXDEMUX(H263, h263); > REGISTER_MUXDEMUX(H264, h264); > + REGISTER_DEMUXER (HEVC, hevc); > REGISTER_MUXDEMUX(HLS, hls); > REGISTER_DEMUXER (IDCIN, idcin); > REGISTER_DEMUXER (IFF, iff); OK > diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c > index 41e1700..648ddc4 100644 > --- a/libavformat/rawdec.c > +++ b/libavformat/rawdec.c > @@ -163,3 +163,7 @@ AVInputFormat ff_shorten_demuxer = { > #if CONFIG_VC1_DEMUXER > FF_DEF_RAWVIDEO_DEMUXER(vc1, "raw VC-1", NULL, "vc1", AV_CODEC_ID_VC1) > #endif > + > +#if CONFIG_HEVC_DEMUXER > +FF_DEF_RAWVIDEO_DEMUXER(hevc, "raw HEVC video format", NULL, > "hevc,h265,265", AV_CODEC_ID_HEVC) > +#endif OK > -- > 1.7.10.4 > > _______________________________________________ > libav-devel mailing list > [email protected] > https://lists.libav.org/mailman/listinfo/libav-devel _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
