@ -281,7 +281,8 @@ static int parse_ext_v2(DOVIContext *s, GetBitContext *gb, AVDOVIDmData *dm,
return 0 ;
}
static int parse_ext_blocks ( DOVIContext * s , GetBitContext * gb , int ver )
static int parse_ext_blocks ( DOVIContext * s , GetBitContext * gb , int ver ,
int compression , int err_recognition )
{
int num_ext_blocks , ext_block_length , start_pos , parsed_bits , ret ;
DOVIExt * ext = s - > ext_blocks ;
@ -296,6 +297,7 @@ static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver)
}
while ( num_ext_blocks - - ) {
AVDOVIDmData dummy ;
AVDOVIDmData * dm ;
uint8_t level ;
@ -304,9 +306,17 @@ static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver)
start_pos = get_bits_count ( gb ) ;
if ( ff_dovi_rpu_extension_is_static ( level ) ) {
if ( ext - > num_static > = FF_ARRAY_ELEMS ( ext - > dm_static ) )
return AVERROR_INVALIDDATA ;
dm = & ext - > dm_static [ ext - > num_static + + ] ;
if ( compression ) {
av_log ( s - > logctx , AV_LOG_WARNING , " Compressed DM RPU contains "
" static extension block level %d \n " , level ) ;
if ( err_recognition & ( AV_EF_AGGRESSIVE | AV_EF_EXPLODE ) )
return AVERROR_INVALIDDATA ;
dm = & dummy ;
} else {
if ( ext - > num_static > = FF_ARRAY_ELEMS ( ext - > dm_static ) )
return AVERROR_INVALIDDATA ;
dm = & ext - > dm_static [ ext - > num_static + + ] ;
}
} else {
if ( ext - > num_dynamic > = FF_ARRAY_ELEMS ( ext - > dm_dynamic ) )
return AVERROR_INVALIDDATA ;
@ -342,6 +352,7 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
uint8_t rpu_type ;
uint8_t vdr_seq_info_present ;
uint8_t vdr_dm_metadata_present ;
uint8_t dm_compression = 0 ;
uint8_t use_prev_vdr_rpu ;
uint8_t use_nlq ;
uint8_t profile ;
@ -454,7 +465,6 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
int bl_bit_depth_minus8 = get_ue_golomb_31 ( gb ) ;
int el_bit_depth_minus8 = get_ue_golomb_long ( gb ) ;
int vdr_bit_depth_minus8 = get_ue_golomb_31 ( gb ) ;
int reserved_zero_3bits ;
/* ext_mapping_idc is in the upper 8 bits of el_bit_depth_minus8 */
int ext_mapping_idc = el_bit_depth_minus8 > > 8 ;
el_bit_depth_minus8 = el_bit_depth_minus8 & 0xFF ;
@ -468,8 +478,7 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
hdr - > ext_mapping_idc_5_7 = ext_mapping_idc > > 5 ;
hdr - > vdr_bit_depth = vdr_bit_depth_minus8 + 8 ;
hdr - > spatial_resampling_filter_flag = get_bits1 ( gb ) ;
reserved_zero_3bits = get_bits ( gb , 3 ) ;
VALIDATE ( reserved_zero_3bits , 0 , 0 ) ;
dm_compression = get_bits ( gb , 3 ) ;
hdr - > el_spatial_resampling_filter_flag = get_bits1 ( gb ) ;
hdr - > disable_residual_flag = get_bits1 ( gb ) ;
}
@ -481,6 +490,17 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
}
vdr_dm_metadata_present = get_bits1 ( gb ) ;
if ( dm_compression > 1 ) {
/* It seems no device supports this */
av_log ( s - > logctx , AV_LOG_ERROR , " Dynamic metadata compression is not "
" yet implemented " ) ;
return AVERROR_PATCHWELCOME ;
} else if ( dm_compression & & ! vdr_dm_metadata_present ) {
av_log ( s - > logctx , AV_LOG_ERROR , " Nonzero DM metadata compression method "
" but no DM metadata present " ) ;
return AVERROR_INVALIDDATA ;
}
use_prev_vdr_rpu = get_bits1 ( gb ) ;
use_nlq = ( hdr - > rpu_format & 0x700 ) = = 0 & & ! hdr - > disable_residual_flag ;
@ -503,6 +523,12 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
" use_prev_vdr_rpu=1 \n " ) ;
return AVERROR_INVALIDDATA ;
}
if ( dm_compression & & ! compression ) {
av_log ( s - > logctx , AV_LOG_ERROR , " Uncompressed RPUs should not use "
" dm_compression=%d \n " , dm_compression ) ;
return AVERROR_INVALIDDATA ;
}
}
if ( use_prev_vdr_rpu ) {
@ -654,46 +680,50 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
s - > color = color = s - > dm ;
color - > dm_metadata_id = affected_dm_id ;
color - > scene_refresh_flag = get_ue_golomb_31 ( gb ) ;
for ( int i = 0 ; i < 9 ; i + + )
color - > ycc_to_rgb_matrix [ i ] = av_make_q ( get_sbits ( gb , 16 ) , 1 < < 13 ) ;
for ( int i = 0 ; i < 3 ; i + + ) {
int denom = profile = = 4 ? ( 1 < < 30 ) : ( 1 < < 28 ) ;
unsigned offset = get_bits_long ( gb , 32 ) ;
if ( offset > INT_MAX ) {
/* Ensure the result fits inside AVRational */
offset > > = 1 ;
denom > > = 1 ;
if ( ! dm_compression ) {
for ( int i = 0 ; i < 9 ; i + + )
color - > ycc_to_rgb_matrix [ i ] = av_make_q ( get_sbits ( gb , 16 ) , 1 < < 13 ) ;
for ( int i = 0 ; i < 3 ; i + + ) {
int denom = profile = = 4 ? ( 1 < < 30 ) : ( 1 < < 28 ) ;
unsigned offset = get_bits_long ( gb , 32 ) ;
if ( offset > INT_MAX ) {
/* Ensure the result fits inside AVRational */
offset > > = 1 ;
denom > > = 1 ;
}
color - > ycc_to_rgb_offset [ i ] = av_make_q ( offset , denom ) ;
}
color - > ycc_to_rgb_offset [ i ] = av_make_q ( offset , denom ) ;
for ( int i = 0 ; i < 9 ; i + + )
color - > rgb_to_lms_matrix [ i ] = av_make_q ( get_sbits ( gb , 16 ) , 1 < < 14 ) ;
color - > signal_eotf = get_bits ( gb , 16 ) ;
color - > signal_eotf_param0 = get_bits ( gb , 16 ) ;
color - > signal_eotf_param1 = get_bits ( gb , 16 ) ;
color - > signal_eotf_param2 = get_bits_long ( gb , 32 ) ;
color - > signal_bit_depth = get_bits ( gb , 5 ) ;
VALIDATE ( color - > signal_bit_depth , 8 , 16 ) ;
color - > signal_color_space = get_bits ( gb , 2 ) ;
color - > signal_chroma_format = get_bits ( gb , 2 ) ;
color - > signal_full_range_flag = get_bits ( gb , 2 ) ;
color - > source_min_pq = get_bits ( gb , 12 ) ;
color - > source_max_pq = get_bits ( gb , 12 ) ;
color - > source_diagonal = get_bits ( gb , 10 ) ;
}
for ( int i = 0 ; i < 9 ; i + + )
color - > rgb_to_lms_matrix [ i ] = av_make_q ( get_sbits ( gb , 16 ) , 1 < < 14 ) ;
color - > signal_eotf = get_bits ( gb , 16 ) ;
color - > signal_eotf_param0 = get_bits ( gb , 16 ) ;
color - > signal_eotf_param1 = get_bits ( gb , 16 ) ;
color - > signal_eotf_param2 = get_bits_long ( gb , 32 ) ;
color - > signal_bit_depth = get_bits ( gb , 5 ) ;
VALIDATE ( color - > signal_bit_depth , 8 , 16 ) ;
color - > signal_color_space = get_bits ( gb , 2 ) ;
color - > signal_chroma_format = get_bits ( gb , 2 ) ;
color - > signal_full_range_flag = get_bits ( gb , 2 ) ;
color - > source_min_pq = get_bits ( gb , 12 ) ;
color - > source_max_pq = get_bits ( gb , 12 ) ;
color - > source_diagonal = get_bits ( gb , 10 ) ;
/* Parse extension blocks */
if ( s - > ext_blocks ) {
DOVIExt * ext = s - > ext_blocks ;
ext - > num_static = ext - > num_dynamic = 0 ;
if ( ! dm_compression )
ext - > num_static = 0 ;
ext - > num_dynamic = 0 ;
}
if ( ( ret = parse_ext_blocks ( s , gb , 1 ) ) < 0 ) {
if ( ( ret = parse_ext_blocks ( s , gb , 1 , dm_compression , err_recognition ) ) < 0 ) {
ff_dovi_ctx_unref ( s ) ;
return ret ;
}
if ( get_bits_left ( gb ) > 48 /* padding + CRC32 + terminator */ ) {
if ( ( ret = parse_ext_blocks ( s , gb , 2 ) ) < 0 ) {
if ( ( ret = parse_ext_blocks ( s , gb , 2 , dm_compression , err_recognition ) ) < 0 ) {
ff_dovi_ctx_unref ( s ) ;
return ret ;
}