static void decode_vui(HEVCContext *s, HEVCSPS *sps) { VUI *vui = &sps->vui; GetBitContext *gb = &s->HEVClc->gb; GetBitContext backup; int sar_present, alt = 0; av_log(s->avctx, AV_LOG_DEBUG, "Decoding VUI\n"); sar_present = get_bits1(gb); if (sar_present) { uint8_t sar_idx = get_bits(gb, 8); if (sar_idx < FF_ARRAY_ELEMS(vui_sar)) vui->sar = vui_sar[sar_idx]; else if (sar_idx == 255) { vui->sar.num = get_bits(gb, 16); vui->sar.den = get_bits(gb, 16); } else av_log(s->avctx, AV_LOG_WARNING, "Unknown SAR index: %u.\n", sar_idx); } vui->overscan_info_present_flag = get_bits1(gb); if (vui->overscan_info_present_flag) vui->overscan_appropriate_flag = get_bits1(gb); vui->video_signal_type_present_flag = get_bits1(gb); if (vui->video_signal_type_present_flag) { vui->video_format = get_bits(gb, 3); vui->video_full_range_flag = get_bits1(gb); vui->colour_description_present_flag = get_bits1(gb); if (vui->video_full_range_flag && sps->pix_fmt == AV_PIX_FMT_YUV420P) sps->pix_fmt = AV_PIX_FMT_YUVJ420P; if (vui->colour_description_present_flag) { vui->colour_primaries = get_bits(gb, 8); vui->transfer_characteristic = get_bits(gb, 8); vui->matrix_coeffs = get_bits(gb, 8); // Set invalid values to "unspecified" if (vui->colour_primaries >= AVCOL_PRI_NB) vui->colour_primaries = AVCOL_PRI_UNSPECIFIED; if (vui->transfer_characteristic >= AVCOL_TRC_NB) vui->transfer_characteristic = AVCOL_TRC_UNSPECIFIED; if (vui->matrix_coeffs >= AVCOL_SPC_NB) vui->matrix_coeffs = AVCOL_SPC_UNSPECIFIED; } } vui->chroma_loc_info_present_flag = get_bits1(gb); if (vui->chroma_loc_info_present_flag) { vui->chroma_sample_loc_type_top_field = get_ue_golomb_long(gb); vui->chroma_sample_loc_type_bottom_field = get_ue_golomb_long(gb); } vui->neutra_chroma_indication_flag = get_bits1(gb); vui->field_seq_flag = get_bits1(gb); vui->frame_field_info_present_flag = get_bits1(gb); vui->default_display_window_flag = get_bits1(gb); // Backup context in case an alternate header is detected if( get_bits_left(gb) >= 66) memcpy(&backup, gb, sizeof(backup)); if (vui->default_display_window_flag) { //TODO: * 2 is only valid for 420 vui->def_disp_win.left_offset = get_ue_golomb_long(gb) * 2; vui->def_disp_win.right_offset = get_ue_golomb_long(gb) * 2; vui->def_disp_win.top_offset = get_ue_golomb_long(gb) * 2; vui->def_disp_win.bottom_offset = get_ue_golomb_long(gb) * 2; if (s->apply_defdispwin && s->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) { av_log(s->avctx, AV_LOG_DEBUG, "discarding vui default display window, " "original values are l:%u r:%u t:%u b:%u\n", vui->def_disp_win.left_offset, vui->def_disp_win.right_offset, vui->def_disp_win.top_offset, vui->def_disp_win.bottom_offset); vui->def_disp_win.left_offset = vui->def_disp_win.right_offset = vui->def_disp_win.top_offset = vui->def_disp_win.bottom_offset = 0; } } vui->vui_timing_info_present_flag = get_bits1(gb); if (vui->vui_timing_info_present_flag) { if( get_bits_left(gb) < 66) { // The alternate syntax seem to have timing info located // at where def_disp_win is normally located av_log(s->avctx, AV_LOG_WARNING, "Strange VUI timing information, retrying...\n"); vui->default_display_window_flag = 0; memset(&vui->def_disp_win, 0, sizeof(vui->def_disp_win)); memcpy(gb, &backup, sizeof(backup)); alt = 1; } vui->vui_num_units_in_tick = get_bits_long(gb, 32); vui->vui_time_scale = get_bits_long(gb, 32); if (alt) { av_log(s->avctx, AV_LOG_INFO, "Retry got %i/%i fps\n", vui->vui_time_scale, vui->vui_num_units_in_tick); } vui->vui_poc_proportional_to_timing_flag = get_bits1(gb); if (vui->vui_poc_proportional_to_timing_flag) vui->vui_num_ticks_poc_diff_one_minus1 = get_ue_golomb_long(gb); vui->vui_hrd_parameters_present_flag = get_bits1(gb); if (vui->vui_hrd_parameters_present_flag) decode_hrd(s, 1, sps->max_sub_layers); } vui->bitstream_restriction_flag = get_bits1(gb); if (vui->bitstream_restriction_flag) { vui->tiles_fixed_structure_flag = get_bits1(gb); vui->motion_vectors_over_pic_boundaries_flag = get_bits1(gb); vui->restricted_ref_pic_lists_flag = get_bits1(gb); vui->min_spatial_segmentation_idc = get_ue_golomb_long(gb); vui->max_bytes_per_pic_denom = get_ue_golomb_long(gb); vui->max_bits_per_min_cu_denom = get_ue_golomb_long(gb); vui->log2_max_mv_length_horizontal = get_ue_golomb_long(gb); vui->log2_max_mv_length_vertical = get_ue_golomb_long(gb); } }