From 73af99ad8a0874d9fa5bc31bfa34ec166faf02a6 Mon Sep 17 00:00:00 2001 From: Khyber Sen Date: Sat, 2 Dec 2023 04:45:33 -0500 Subject: [PATCH 1/2] `mod obu`: Add back `continue`s lost in transpilation. --- src/obu.rs | 107 ++++++++++++++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/src/obu.rs b/src/obu.rs index 892ad8aec..4b39aff5f 100644 --- a/src/obu.rs +++ b/src/obu.rs @@ -1435,48 +1435,48 @@ unsafe fn parse_frame_hdr(c: &mut Rav1dContext, gb: &mut GetBits) -> Rav1dResult } else { RAV1D_WM_TYPE_AFFINE }; - if !(hdr.gmv[i as usize].r#type == RAV1D_WM_TYPE_IDENTITY) { - let ref_gmv; - if hdr.primary_ref_frame == RAV1D_PRIMARY_REF_NONE { - ref_gmv = &dav1d_default_wm_params; - } else { - let pri_ref = hdr.refidx[hdr.primary_ref_frame as usize]; - if (c.refs[pri_ref as usize].p.p.frame_hdr).is_null() { - return error(c); - } - ref_gmv = &mut (*c.refs[pri_ref as usize].p.p.frame_hdr).gmv[i as usize]; - } - let mat = &mut hdr.gmv[i as usize].matrix; - let ref_mat = &ref_gmv.matrix; - let bits; - let shift; - - if hdr.gmv[i as usize].r#type >= RAV1D_WM_TYPE_ROT_ZOOM { - mat[2] = ((1) << 16) - + 2 * rav1d_get_bits_subexp(gb, ref_mat[2] - ((1) << 16) >> 1, 12); - mat[3] = 2 * rav1d_get_bits_subexp(gb, ref_mat[3] >> 1, 12); - - bits = 12; - shift = 10; - } else { - bits = 9 - (hdr.hp == 0) as c_int; - shift = 13 + (hdr.hp == 0) as c_int; - } + if hdr.gmv[i as usize].r#type == RAV1D_WM_TYPE_IDENTITY { + continue; + } - if hdr.gmv[i as usize].r#type as c_uint == RAV1D_WM_TYPE_AFFINE as c_int as c_uint { - mat[4] = 2 * rav1d_get_bits_subexp(gb, ref_mat[4] >> 1, 12); - mat[5] = (1 << 16) - + 2 * rav1d_get_bits_subexp(gb, ref_mat[5] - ((1) << 16) >> 1, 12); - } else { - mat[4] = -mat[3]; - mat[5] = mat[2]; + let ref_gmv; + if hdr.primary_ref_frame == RAV1D_PRIMARY_REF_NONE { + ref_gmv = &dav1d_default_wm_params; + } else { + let pri_ref = hdr.refidx[hdr.primary_ref_frame as usize]; + if (c.refs[pri_ref as usize].p.p.frame_hdr).is_null() { + return error(c); } + ref_gmv = &mut (*c.refs[pri_ref as usize].p.p.frame_hdr).gmv[i as usize]; + } + let mat = &mut hdr.gmv[i as usize].matrix; + let ref_mat = &ref_gmv.matrix; + let bits; + let shift; + + if hdr.gmv[i as usize].r#type >= RAV1D_WM_TYPE_ROT_ZOOM { + mat[2] = + ((1) << 16) + 2 * rav1d_get_bits_subexp(gb, ref_mat[2] - ((1) << 16) >> 1, 12); + mat[3] = 2 * rav1d_get_bits_subexp(gb, ref_mat[3] >> 1, 12); + + bits = 12; + shift = 10; + } else { + bits = 9 - (hdr.hp == 0) as c_int; + shift = 13 + (hdr.hp == 0) as c_int; + } - mat[0] = - rav1d_get_bits_subexp(gb, ref_mat[0] >> shift, bits as c_uint) * (1 << shift); - mat[1] = - rav1d_get_bits_subexp(gb, ref_mat[1] >> shift, bits as c_uint) * (1 << shift); + if hdr.gmv[i as usize].r#type as c_uint == RAV1D_WM_TYPE_AFFINE as c_int as c_uint { + mat[4] = 2 * rav1d_get_bits_subexp(gb, ref_mat[4] >> 1, 12); + mat[5] = + (1 << 16) + 2 * rav1d_get_bits_subexp(gb, ref_mat[5] - ((1) << 16) >> 1, 12); + } else { + mat[4] = -mat[3]; + mat[5] = mat[2]; } + + mat[0] = rav1d_get_bits_subexp(gb, ref_mat[0] >> shift, bits as c_uint) * (1 << shift); + mat[1] = rav1d_get_bits_subexp(gb, ref_mat[1] >> shift, bits as c_uint) * (1 << shift); } } if DEBUG_FRAME_HDR { @@ -2345,25 +2345,24 @@ pub(crate) unsafe fn rav1d_parse_obus( let r = (*c.frame_hdr).existing_frame_idx; c.refs[r as usize].p.showable = false; for i in 0..8 { - if !(i == r) { - if !c.refs[i as usize].p.p.frame_hdr.is_null() { - rav1d_thread_picture_unref(&mut c.refs[i as usize].p); - } - rav1d_thread_picture_ref( - &mut c.refs[i as usize].p, - &mut c.refs[r as usize].p, - ); + if i == r { + continue; + } + + if !c.refs[i as usize].p.p.frame_hdr.is_null() { + rav1d_thread_picture_unref(&mut c.refs[i as usize].p); + } + rav1d_thread_picture_ref(&mut c.refs[i as usize].p, &mut c.refs[r as usize].p); - rav1d_cdf_thread_unref(&mut c.cdf[i as usize]); - rav1d_cdf_thread_ref(&mut c.cdf[i as usize], &mut c.cdf[r as usize]); + rav1d_cdf_thread_unref(&mut c.cdf[i as usize]); + rav1d_cdf_thread_ref(&mut c.cdf[i as usize], &mut c.cdf[r as usize]); - rav1d_ref_dec(&mut c.refs[i as usize].segmap); - c.refs[i as usize].segmap = c.refs[r as usize].segmap; - if !c.refs[r as usize].segmap.is_null() { - rav1d_ref_inc(c.refs[r as usize].segmap); - } - rav1d_ref_dec(&mut c.refs[i as usize].refmvs); + rav1d_ref_dec(&mut c.refs[i as usize].segmap); + c.refs[i as usize].segmap = c.refs[r as usize].segmap; + if !c.refs[r as usize].segmap.is_null() { + rav1d_ref_inc(c.refs[r as usize].segmap); } + rav1d_ref_dec(&mut c.refs[i as usize].refmvs); } } c.frame_hdr = 0 as *mut Rav1dFrameHeader; From bc0f83abe5399ec42865e183040e743f9aa17148 Mon Sep 17 00:00:00 2001 From: Khyber Sen Date: Sat, 2 Dec 2023 05:10:24 -0500 Subject: [PATCH 2/2] `fn rav1d_parse_obus`: Turn early `break`s and fall-throughs in a `switch` into a state machine with `break`s and `continue`s. This was already transpiled as a `current_block_[0-9]+` state machine, but this is a state machine with a forever `loop` to early `break` out of, and a `state` scrutinee to switch to and `continue` for fall-throughs, so it's much more readable and similar to the C early `break`s and fall-throughs. --- src/obu.rs | 615 ++++++++++++++++++++++++++--------------------------- 1 file changed, 296 insertions(+), 319 deletions(-) diff --git a/src/obu.rs b/src/obu.rs index 4b39aff5f..4cdbc8965 100644 --- a/src/obu.rs +++ b/src/obu.rs @@ -1770,312 +1770,89 @@ pub(crate) unsafe fn rav1d_parse_obus( return Ok(len + init_byte_pos); } } - let mut current_block_188: u64; - match r#type { - RAV1D_OBU_SEQ_HDR => { - let mut r#ref = rav1d_ref_create_using_pool( - c.seq_hdr_pool, - ::core::mem::size_of::>(), - ); - if r#ref.is_null() { - return Err(ENOMEM); - } - let seq_hdrs = (*r#ref) - .data - .cast::>(); - let seq_hdr = addr_of_mut!((*seq_hdrs).rav1d); - let res = parse_seq_hdr(c, &mut gb, &mut *seq_hdr); - (*seq_hdrs).update_dav1d(); - if res.is_err() { - rav1d_ref_dec(&mut r#ref); - error(c, r#in)?; - } - if check_for_overrun(c, &mut gb, init_bit_pos, len) != 0 { - rav1d_ref_dec(&mut r#ref); - error(c, r#in)?; - } - // If we have read a sequence header which is different from the old one, - // this is a new video sequence and can't use any previous state. - // Free that state. - - if c.seq_hdr.is_null() { - c.frame_hdr = 0 as *mut Rav1dFrameHeader; - c.frame_flags |= PICTURE_FLAG_NEW_SEQUENCE; - } else if memcmp( - seq_hdr as *const c_void, - c.seq_hdr as *const c_void, - // TODO(kkysen) Remove unstable feature. - // Doing it this way also prevents us from removing the `#[repr(C)]`. - // We should split [`Rav1dSequenceHeader`] into an inner `struct` - // without the `operating_parameter_info` field, - // or at least offer safe field-by-field comparison methods. - mem::offset_of!(Rav1dSequenceHeader, operating_parameter_info), - ) != 0 - { - // See 7.5, `operating_parameter_info` is allowed to change in - // sequence headers of a single sequence. - c.frame_hdr = 0 as *mut Rav1dFrameHeader; - c.mastering_display = 0 as *mut Rav1dMasteringDisplay; - c.content_light = 0 as *mut Rav1dContentLightLevel; - rav1d_ref_dec(&mut c.mastering_display_ref); - rav1d_ref_dec(&mut c.content_light_ref); - for i in 0..8 { - if !c.refs[i as usize].p.p.frame_hdr.is_null() { - rav1d_thread_picture_unref(&mut c.refs[i as usize].p); - } - rav1d_ref_dec(&mut c.refs[i as usize].segmap); - rav1d_ref_dec(&mut c.refs[i as usize].refmvs); - rav1d_cdf_thread_unref(&mut c.cdf[i as usize]); + let mut state = r#type; + loop { + match state { + RAV1D_OBU_SEQ_HDR => { + let mut r#ref = rav1d_ref_create_using_pool( + c.seq_hdr_pool, + ::core::mem::size_of::>(), + ); + if r#ref.is_null() { + return Err(ENOMEM); } - c.frame_flags |= PICTURE_FLAG_NEW_SEQUENCE; - } else if memcmp( - ((*seq_hdr).operating_parameter_info).as_mut_ptr() as *const c_void, - ((*c.seq_hdr).operating_parameter_info).as_mut_ptr() as *const c_void, - ::core::mem::size_of::<[Dav1dSequenceHeaderOperatingParameterInfo; 32]>(), - ) != 0 - { - // If operating_parameter_info changed, signal it - c.frame_flags |= PICTURE_FLAG_NEW_OP_PARAMS_INFO; - } - rav1d_ref_dec(&mut c.seq_hdr_ref); - c.seq_hdr_ref = r#ref; - c.seq_hdr = seq_hdr; - current_block_188 = 8953117030348968745; // break; - } - RAV1D_OBU_REDUNDANT_FRAME_HDR => { - if !c.frame_hdr.is_null() { - current_block_188 = 8953117030348968745; // break; - } else { - // fall-through - current_block_188 = 14065157188459580465; - } - } - RAV1D_OBU_FRAME | RAV1D_OBU_FRAME_HDR => { - current_block_188 = 14065157188459580465; - } - RAV1D_OBU_TILE_GRP => { - current_block_188 = 17787701279558130514; - } - RAV1D_OBU_METADATA => { - const DEBUG_OBU_METADATA: bool = false; - let init_ptr = gb.ptr; - - // obu metadata type field - let meta_type = rav1d_get_uleb128(&mut gb) as ObuMetaType; - let meta_type_len = ((rav1d_get_bits_pos(&mut gb) - init_bit_pos) >> 3) as c_int; - if gb.error != 0 { - error(c, r#in)?; - } - - match meta_type { - OBU_META_HDR_CLL => { - let mut r#ref = - rav1d_ref_create(::core::mem::size_of::()); - if r#ref.is_null() { - return Err(ENOMEM); - } - let content_light = (*r#ref).data as *mut Rav1dContentLightLevel; - - (*content_light).max_content_light_level = rav1d_get_bits(&mut gb, 16) as c_int; - if DEBUG_OBU_METADATA { - println!( - "CLLOBU: max-content-light-level: {} [off={}]", - (*content_light).max_content_light_level, - gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize - ); - } - (*content_light).max_frame_average_light_level = - rav1d_get_bits(&mut gb, 16) as c_int; - if DEBUG_OBU_METADATA { - println!( - "CLLOBU: max-frame-average-light-level: {} [off={}]", - (*content_light).max_frame_average_light_level, - gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize - ); - } - - // Skip the trailing bit, align to the next byte boundary and check for overrun. - rav1d_get_bit(&mut gb); - rav1d_bytealign_get_bits(&mut gb); - if check_for_overrun(c, &mut gb, init_bit_pos, len) != 0 { - rav1d_ref_dec(&mut r#ref); - error(c, r#in)?; - } - - rav1d_ref_dec(&mut c.content_light_ref); - c.content_light = content_light; - c.content_light_ref = r#ref; + let seq_hdrs = (*r#ref) + .data + .cast::>(); + let seq_hdr = addr_of_mut!((*seq_hdrs).rav1d); + let res = parse_seq_hdr(c, &mut gb, &mut *seq_hdr); + (*seq_hdrs).update_dav1d(); + if res.is_err() { + rav1d_ref_dec(&mut r#ref); + error(c, r#in)?; } - OBU_META_HDR_MDCV => { - let mut r#ref = - rav1d_ref_create(::core::mem::size_of::()); - if r#ref.is_null() { - return Err(ENOMEM); - } - let mastering_display = (*r#ref).data as *mut Rav1dMasteringDisplay; - - for i in 0..3 { - (*mastering_display).primaries[i as usize][0] = - rav1d_get_bits(&mut gb, 16) as u16; - (*mastering_display).primaries[i as usize][1] = - rav1d_get_bits(&mut gb, 16) as u16; - if DEBUG_OBU_METADATA { - println!( - "MDCVOBU: primaries[{}]: ({}, {}) [off={}]", - i, - (*mastering_display).primaries[i as usize][0], - (*mastering_display).primaries[i as usize][1], - gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize - ); - } - } - (*mastering_display).white_point[0] = rav1d_get_bits(&mut gb, 16) as u16; - if DEBUG_OBU_METADATA { - println!( - "CLLOBU: white-point-x: {} [off={}]", - (*mastering_display).white_point[0], - gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize - ); - } - (*mastering_display).white_point[1] = rav1d_get_bits(&mut gb, 16) as u16; - if DEBUG_OBU_METADATA { - println!( - "CLLOBU: white-point-y: {} [off={}]", - (*mastering_display).white_point[1], - gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize - ); - } - (*mastering_display).max_luminance = rav1d_get_bits(&mut gb, 32); - if DEBUG_OBU_METADATA { - println!( - "CLLOBU: max-luminance: {} [off={}]", - (*mastering_display).max_luminance, - gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize - ); - } - (*mastering_display).min_luminance = rav1d_get_bits(&mut gb, 32); - if DEBUG_OBU_METADATA { - println!( - "CLLOBU: min-luminance: {} [off={}]", - (*mastering_display).min_luminance, - gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize - ); - } - // Skip the trailing bit, align to the next byte boundary and check for overrun. - rav1d_get_bit(&mut gb); - rav1d_bytealign_get_bits(&mut gb); - if check_for_overrun(c, &mut gb, init_bit_pos, len) != 0 { - rav1d_ref_dec(&mut r#ref); - error(c, r#in)?; - } + if check_for_overrun(c, &mut gb, init_bit_pos, len) != 0 { + rav1d_ref_dec(&mut r#ref); + error(c, r#in)?; + } + // If we have read a sequence header which is different from the old one, + // this is a new video sequence and can't use any previous state. + // Free that state. + if c.seq_hdr.is_null() { + c.frame_hdr = 0 as *mut Rav1dFrameHeader; + c.frame_flags |= PICTURE_FLAG_NEW_SEQUENCE; + } else if memcmp( + seq_hdr as *const c_void, + c.seq_hdr as *const c_void, + // TODO(kkysen) Remove unstable feature. + // Doing it this way also prevents us from removing the `#[repr(C)]`. + // We should split [`Rav1dSequenceHeader`] into an inner `struct` + // without the `operating_parameter_info` field, + // or at least offer safe field-by-field comparison methods. + mem::offset_of!(Rav1dSequenceHeader, operating_parameter_info), + ) != 0 + { + // See 7.5, `operating_parameter_info` is allowed to change in + // sequence headers of a single sequence. + c.frame_hdr = 0 as *mut Rav1dFrameHeader; + c.mastering_display = 0 as *mut Rav1dMasteringDisplay; + c.content_light = 0 as *mut Rav1dContentLightLevel; rav1d_ref_dec(&mut c.mastering_display_ref); - c.mastering_display = mastering_display; - c.mastering_display_ref = r#ref; - } - OBU_META_ITUT_T35 => { - let mut payload_size = len as c_int; - // Don't take into account all the trailing bits for `payload_size`. - while payload_size > 0 - && *r#in - .data - .offset((init_byte_pos + payload_size as c_uint - 1) as isize) - == 0 - { - payload_size -= 1; // trailing_zero_bit x 8 - } - payload_size -= 1; // trailing_one_bit + trailing_zero_bit x 7 - - // Don't take into account meta_type bytes - payload_size -= meta_type_len; - - let mut country_code_extension_byte = 0; - let country_code = rav1d_get_bits(&mut gb, 8) as c_int; - payload_size -= 1; - if country_code == 0xff { - country_code_extension_byte = rav1d_get_bits(&mut gb, 8) as c_int; - payload_size -= 1; - } - - if payload_size <= 0 { - rav1d_log( - c, - b"Malformed ITU-T T.35 metadata message format\n\0" as *const u8 - as *const c_char, - ); - } else { - let r#ref = rav1d_ref_create( - ::core::mem::size_of::>() - + payload_size as usize * ::core::mem::size_of::(), - ); - if r#ref.is_null() { - return Err(ENOMEM); - } - let itut_t32_metadatas = - (*r#ref).data.cast::>(); - let itut_t35_metadata = addr_of_mut!((*itut_t32_metadatas).rav1d); - - // We need our public headers to be C++ compatible, so payload can't be - // a flexible array member - (*itut_t35_metadata).payload = (*r#ref) - .data - .cast::() - .offset(::core::mem::size_of::>() - as isize); - (*itut_t35_metadata).country_code = country_code as u8; - (*itut_t35_metadata).country_code_extension_byte = - country_code_extension_byte as u8; - for i in 0..payload_size { - *((*itut_t35_metadata).payload).offset(i as isize) = - rav1d_get_bits(&mut gb, 8) as u8; + rav1d_ref_dec(&mut c.content_light_ref); + for i in 0..8 { + if !c.refs[i as usize].p.p.frame_hdr.is_null() { + rav1d_thread_picture_unref(&mut c.refs[i as usize].p); } - (*itut_t35_metadata).payload_size = payload_size as usize; - (*itut_t32_metadatas).update_dav1d(); - - rav1d_ref_dec(&mut c.itut_t35_ref); - c.itut_t35 = itut_t35_metadata; - c.itut_t35_ref = r#ref; + rav1d_ref_dec(&mut c.refs[i as usize].segmap); + rav1d_ref_dec(&mut c.refs[i as usize].refmvs); + rav1d_cdf_thread_unref(&mut c.cdf[i as usize]); } + c.frame_flags |= PICTURE_FLAG_NEW_SEQUENCE; + } else if memcmp( + ((*seq_hdr).operating_parameter_info).as_mut_ptr() as *const c_void, + ((*c.seq_hdr).operating_parameter_info).as_mut_ptr() as *const c_void, + ::core::mem::size_of::<[Dav1dSequenceHeaderOperatingParameterInfo; 32]>(), + ) != 0 + { + // If operating_parameter_info changed, signal it + c.frame_flags |= PICTURE_FLAG_NEW_OP_PARAMS_INFO; } - OBU_META_SCALABILITY | OBU_META_TIMECODE => { - // Ignore metadata OBUs we don't care about. - } - _ => { - // Print a warning, but don't fail for unknown types. - rav1d_log( - c, - b"Unknown Metadata OBU type %d\n\0" as *const u8 as *const c_char, - meta_type as c_uint, - ); + rav1d_ref_dec(&mut c.seq_hdr_ref); + c.seq_hdr_ref = r#ref; + c.seq_hdr = seq_hdr; + } + RAV1D_OBU_REDUNDANT_FRAME_HDR => { + if c.frame_hdr.is_null() { + state = RAV1D_OBU_FRAME; + continue; // fall-through } } - current_block_188 = 8953117030348968745; - } - RAV1D_OBU_TD => { - c.frame_flags |= PICTURE_FLAG_NEW_TEMPORAL_UNIT; - current_block_188 = 8953117030348968745; // break; - } - RAV1D_OBU_PADDING => { - // Ignore OBUs we don't care about. - current_block_188 = 8953117030348968745; // break; - } - _ => { - // Print a warning, but don't fail for unknown types. - rav1d_log( - c, - b"Unknown OBU type %d of size %u\n\0" as *const u8 as *const c_char, - r#type as c_uint, - len, - ); - current_block_188 = 8953117030348968745; // break; - } - } - match current_block_188 { - 14065157188459580465 => { - if global != 0 { - current_block_188 = 8953117030348968745; // break; - } else { + RAV1D_OBU_FRAME | RAV1D_OBU_FRAME_HDR => { + if global != 0 { + break; + } if c.seq_hdr.is_null() { error(c, r#in)?; } @@ -2136,27 +1913,25 @@ pub(crate) unsafe fn rav1d_parse_obus( } if r#type != RAV1D_OBU_FRAME { - current_block_188 = 8953117030348968745; // break; - } else { - // OBU_FRAMEs shouldn't be signaled with `show_existing_frame`. - if (*c.frame_hdr).show_existing_frame != 0 { - c.frame_hdr = 0 as *mut Rav1dFrameHeader; - error(c, r#in)?; - } - - // This is the frame header at the start of a frame OBU. - // There's no trailing bit at the end to skip, - // but we do need to align to the next byte. - rav1d_bytealign_get_bits(&mut gb); - current_block_188 = 17787701279558130514; // fall-through + break; + } + // OBU_FRAMEs shouldn't be signaled with `show_existing_frame`. + if (*c.frame_hdr).show_existing_frame != 0 { + c.frame_hdr = 0 as *mut Rav1dFrameHeader; + error(c, r#in)?; } + + // This is the frame header at the start of a frame OBU. + // There's no trailing bit at the end to skip, + // but we do need to align to the next byte. + rav1d_bytealign_get_bits(&mut gb); + state = RAV1D_OBU_TILE_GRP; + continue; // fall-through } - } - _ => {} - } - match current_block_188 { - 17787701279558130514 => { - if !(global != 0) { + RAV1D_OBU_TILE_GRP => { + if global != 0 { + break; + } if c.frame_hdr.is_null() { error(c, r#in)?; } @@ -2217,12 +1992,214 @@ pub(crate) unsafe fn rav1d_parse_obus( c.n_tiles += 1 + (*(c.tile).offset(c.n_tile_data as isize)).end - (*(c.tile).offset(c.n_tile_data as isize)).start; c.n_tile_data += 1; - // break; - } else { - // break; + } + RAV1D_OBU_METADATA => { + const DEBUG_OBU_METADATA: bool = false; + let init_ptr = gb.ptr; + + // obu metadata type field + let meta_type = rav1d_get_uleb128(&mut gb) as ObuMetaType; + let meta_type_len = ((rav1d_get_bits_pos(&mut gb) - init_bit_pos) >> 3) as c_int; + if gb.error != 0 { + error(c, r#in)?; + } + + match meta_type { + OBU_META_HDR_CLL => { + let mut r#ref = + rav1d_ref_create(::core::mem::size_of::()); + if r#ref.is_null() { + return Err(ENOMEM); + } + let content_light = (*r#ref).data as *mut Rav1dContentLightLevel; + + (*content_light).max_content_light_level = + rav1d_get_bits(&mut gb, 16) as c_int; + if DEBUG_OBU_METADATA { + println!( + "CLLOBU: max-content-light-level: {} [off={}]", + (*content_light).max_content_light_level, + gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize + ); + } + (*content_light).max_frame_average_light_level = + rav1d_get_bits(&mut gb, 16) as c_int; + if DEBUG_OBU_METADATA { + println!( + "CLLOBU: max-frame-average-light-level: {} [off={}]", + (*content_light).max_frame_average_light_level, + gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize + ); + } + + // Skip the trailing bit, align to the next byte boundary and check for overrun. + rav1d_get_bit(&mut gb); + rav1d_bytealign_get_bits(&mut gb); + if check_for_overrun(c, &mut gb, init_bit_pos, len) != 0 { + rav1d_ref_dec(&mut r#ref); + error(c, r#in)?; + } + + rav1d_ref_dec(&mut c.content_light_ref); + c.content_light = content_light; + c.content_light_ref = r#ref; + } + OBU_META_HDR_MDCV => { + let mut r#ref = + rav1d_ref_create(::core::mem::size_of::()); + if r#ref.is_null() { + return Err(ENOMEM); + } + let mastering_display = (*r#ref).data as *mut Rav1dMasteringDisplay; + + for i in 0..3 { + (*mastering_display).primaries[i as usize][0] = + rav1d_get_bits(&mut gb, 16) as u16; + (*mastering_display).primaries[i as usize][1] = + rav1d_get_bits(&mut gb, 16) as u16; + if DEBUG_OBU_METADATA { + println!( + "MDCVOBU: primaries[{}]: ({}, {}) [off={}]", + i, + (*mastering_display).primaries[i as usize][0], + (*mastering_display).primaries[i as usize][1], + gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize + ); + } + } + (*mastering_display).white_point[0] = rav1d_get_bits(&mut gb, 16) as u16; + if DEBUG_OBU_METADATA { + println!( + "CLLOBU: white-point-x: {} [off={}]", + (*mastering_display).white_point[0], + gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize + ); + } + (*mastering_display).white_point[1] = rav1d_get_bits(&mut gb, 16) as u16; + if DEBUG_OBU_METADATA { + println!( + "CLLOBU: white-point-y: {} [off={}]", + (*mastering_display).white_point[1], + gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize + ); + } + (*mastering_display).max_luminance = rav1d_get_bits(&mut gb, 32); + if DEBUG_OBU_METADATA { + println!( + "CLLOBU: max-luminance: {} [off={}]", + (*mastering_display).max_luminance, + gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize + ); + } + (*mastering_display).min_luminance = rav1d_get_bits(&mut gb, 32); + if DEBUG_OBU_METADATA { + println!( + "CLLOBU: min-luminance: {} [off={}]", + (*mastering_display).min_luminance, + gb.ptr.offset_from(init_ptr) * 8 - gb.bits_left as isize + ); + } + // Skip the trailing bit, align to the next byte boundary and check for overrun. + rav1d_get_bit(&mut gb); + rav1d_bytealign_get_bits(&mut gb); + if check_for_overrun(c, &mut gb, init_bit_pos, len) != 0 { + rav1d_ref_dec(&mut r#ref); + error(c, r#in)?; + } + + rav1d_ref_dec(&mut c.mastering_display_ref); + c.mastering_display = mastering_display; + c.mastering_display_ref = r#ref; + } + OBU_META_ITUT_T35 => { + let mut payload_size = len as c_int; + // Don't take into account all the trailing bits for `payload_size`. + while payload_size > 0 + && *r#in + .data + .offset((init_byte_pos + payload_size as c_uint - 1) as isize) + == 0 + { + payload_size -= 1; // trailing_zero_bit x 8 + } + payload_size -= 1; // trailing_one_bit + trailing_zero_bit x 7 + + // Don't take into account meta_type bytes + payload_size -= meta_type_len; + + let mut country_code_extension_byte = 0; + let country_code = rav1d_get_bits(&mut gb, 8) as c_int; + payload_size -= 1; + if country_code == 0xff { + country_code_extension_byte = rav1d_get_bits(&mut gb, 8) as c_int; + payload_size -= 1; + } + + if payload_size <= 0 { + rav1d_log( + c, + b"Malformed ITU-T T.35 metadata message format\n\0" as *const u8 + as *const c_char, + ); + } else { + let r#ref = rav1d_ref_create( + ::core::mem::size_of::>() + + payload_size as usize * ::core::mem::size_of::(), + ); + if r#ref.is_null() { + return Err(ENOMEM); + } + let itut_t32_metadatas = + (*r#ref).data.cast::>(); + let itut_t35_metadata = addr_of_mut!((*itut_t32_metadatas).rav1d); + + // We need our public headers to be C++ compatible, so payload can't be + // a flexible array member + (*itut_t35_metadata).payload = + (*r#ref).data.cast::().offset(::core::mem::size_of::< + DRav1d, + >( + ) + as isize); + (*itut_t35_metadata).country_code = country_code as u8; + (*itut_t35_metadata).country_code_extension_byte = + country_code_extension_byte as u8; + for i in 0..payload_size { + *((*itut_t35_metadata).payload).offset(i as isize) = + rav1d_get_bits(&mut gb, 8) as u8; + } + (*itut_t35_metadata).payload_size = payload_size as usize; + (*itut_t32_metadatas).update_dav1d(); + + rav1d_ref_dec(&mut c.itut_t35_ref); + c.itut_t35 = itut_t35_metadata; + c.itut_t35_ref = r#ref; + } + } + OBU_META_SCALABILITY | OBU_META_TIMECODE => {} // Ignore metadata OBUs we don't care about. + _ => { + // Print a warning, but don't fail for unknown types. + rav1d_log( + c, + b"Unknown Metadata OBU type %d\n\0" as *const u8 as *const c_char, + meta_type as c_uint, + ); + } + } + } + RAV1D_OBU_TD => c.frame_flags |= PICTURE_FLAG_NEW_TEMPORAL_UNIT, + RAV1D_OBU_PADDING => {} // Ignore OBUs we don't care about. + _ => { + // Print a warning, but don't fail for unknown types. + rav1d_log( + c, + b"Unknown OBU type %d of size %u\n\0" as *const u8 as *const c_char, + r#type as c_uint, + len, + ); } } - _ => {} + break; } if !c.seq_hdr.is_null() && !c.frame_hdr.is_null() {