Commit 0625a380 authored by Christophe Gisquet's avatar Christophe Gisquet Committed by Michael Niedermayer

hevc_ps: check overflow and test alternate syntax

Some streams were found to have what appeared to be truncated SPS.
Their syntax seem to be valid at least until the end of the VUI, so
try that syntax if the parsing would overflow the SPS in the
conforming syntax.

Fixes ticket #3872.
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent fca76dc6
...@@ -471,7 +471,8 @@ static void decode_vui(HEVCContext *s, HEVCSPS *sps) ...@@ -471,7 +471,8 @@ static void decode_vui(HEVCContext *s, HEVCSPS *sps)
{ {
VUI *vui = &sps->vui; VUI *vui = &sps->vui;
GetBitContext *gb = &s->HEVClc->gb; GetBitContext *gb = &s->HEVClc->gb;
int sar_present; GetBitContext backup;
int sar_present, alt = 1;
av_log(s->avctx, AV_LOG_DEBUG, "Decoding VUI\n"); av_log(s->avctx, AV_LOG_DEBUG, "Decoding VUI\n");
...@@ -525,6 +526,10 @@ static void decode_vui(HEVCContext *s, HEVCSPS *sps) ...@@ -525,6 +526,10 @@ static void decode_vui(HEVCContext *s, HEVCSPS *sps)
vui->frame_field_info_present_flag = get_bits1(gb); vui->frame_field_info_present_flag = get_bits1(gb);
vui->default_display_window_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) { if (vui->default_display_window_flag) {
//TODO: * 2 is only valid for 420 //TODO: * 2 is only valid for 420
vui->def_disp_win.left_offset = get_ue_golomb_long(gb) * 2; vui->def_disp_win.left_offset = get_ue_golomb_long(gb) * 2;
...@@ -552,8 +557,22 @@ static void decode_vui(HEVCContext *s, HEVCSPS *sps) ...@@ -552,8 +557,22 @@ static void decode_vui(HEVCContext *s, HEVCSPS *sps)
vui->vui_timing_info_present_flag = get_bits1(gb); vui->vui_timing_info_present_flag = get_bits1(gb);
if (vui->vui_timing_info_present_flag) { 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_num_units_in_tick = get_bits_long(gb, 32);
vui->vui_time_scale = 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); vui->vui_poc_proportional_to_timing_flag = get_bits1(gb);
if (vui->vui_poc_proportional_to_timing_flag) if (vui->vui_poc_proportional_to_timing_flag)
vui->vui_num_ticks_poc_diff_one_minus1 = get_ue_golomb_long(gb); vui->vui_num_ticks_poc_diff_one_minus1 = get_ue_golomb_long(gb);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment