From fe71478e68464b63ee6cdb1a01eddb5b7606f9ea Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Sat, 4 May 2024 03:24:01 +0200 Subject: [PATCH] sequence header OBU is (kinda) done, frame OBU is WIP --- avif.odin | 11 +- obu.odin | 981 +++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 763 insertions(+), 229 deletions(-) diff --git a/avif.odin b/avif.odin index a4e7419..c20481f 100644 --- a/avif.odin +++ b/avif.odin @@ -76,6 +76,7 @@ ISOBMFFBrand :: enum u32 { AVIO = 'a' << 24 | 'v' << 16 | 'i' << 8 | 'o', MSF1 = 'm' << 24 | 's' << 16 | 'f' << 8 | '1', AV01 = 'a' << 24 | 'v' << 16 | '0' << 8 | '1', + ISO8 = 'i' << 24 | 's' << 16 | 'o' << 8 | '8', } HEIFTrack :: enum u32 { @@ -176,11 +177,13 @@ read_box :: proc(img: ^Image, reader: ^Reader) -> (err: io.Error) { @(private) read_mdat :: proc(reader: ^Reader) { + seq_header: SequenceHeader + frame_header: FrameHeader // TODO: - read_obu(reader) - read_obu(reader) - read_obu(reader) - read_obu(reader) + read_obu(reader, &seq_header, &frame_header) + read_obu(reader, &seq_header, &frame_header) + read_obu(reader, &seq_header, &frame_header) + read_obu(reader, &seq_header, &frame_header) } @(private) diff --git a/obu.odin b/obu.odin index 92314c8..1ab2010 100644 --- a/obu.odin +++ b/obu.odin @@ -3,6 +3,16 @@ package avif import "core:fmt" import "core:io" +SELECT_SCREEN_CONTENT_TOOLS :: 2 +SELECT_INTEGER_MV :: 2 +MAX_OPERATING_POINTS :: 32 +MAX_TILE_COLS :: 64 +MAX_TILE_ROWS :: 64 +NUM_REF_FRAMES :: 8 +REFS_PER_FRAME :: 7 +PRIMARY_REF_NONE :: 7 +MAX_SEGMENTS :: 8 + OBUType :: enum u8 { SEQUENCE_HEADER = 1, TEMPORAL_DELIMITER = 2, @@ -17,6 +27,7 @@ OBUType :: enum u8 { OBUError :: enum { ReservedOBU, + ReservedSeqProfile, } ColorPrimaries :: enum u8 { @@ -81,6 +92,42 @@ ChromeSamplePosition :: enum u8 { RESERVED = 3, } +ColorRange :: enum u8 { + LIMITED = 0, + FULL = 1, +} + +FrameType :: enum u8 { + KEY_FRAME = 0, + INTER_FRAME = 1, + INTRA_ONLY_FRAME = 2, + SWITCH_FRAME = 3, +} + +// Maybe just make these constants?? +RefFrame0 :: enum u8 { + INTRA_FRAME = 0, + LAST_FRAME = 1, + LAST2_FRAME = 2, + LAST3_FRAME = 3, + GOLDEN_FRAME = 4, + BWDREF_FRAME = 5, + ALTREF2_FRAME = 6, + ALTREF_FRAME = 7, +} + +RefFrame1 :: enum i8 { + NONE = -1, + INTRA_FRAME = 0, + LAST_FRAME = 1, + LAST2_FRAME = 2, + LAST3_FRAME = 3, + GOLDEN_FRAME = 4, + BWDREF_FRAME = 5, + ALTREF2_FRAME = 6, + ALTREF_FRAME = 7, +} + OBUHeader :: bit_field u8 { obu_reserved: u8 | 1, obu_has_size_field: b8 | 1, @@ -95,7 +142,54 @@ OBUExtensionHeader :: bit_field u8 { temporal_id: u8 | 3, } -read_obu :: proc(r: ^Reader) -> (err: Error) { +SequenceHeader :: struct { + enable_superres: bool, + enable_cdef: bool, + enable_restoration: bool, + film_grain_params_present: bool, + seq_profile: u8, + BitDepth: u8, + mono_chrome: bool, + num_planes: u8, + color_primaries: ColorPrimaries, + transfer_characteristic: TransferCharacteristic, + matrix_coefficients: MatrixCoefficient, + chroma_sample_position: ChromeSamplePosition, + subsampling_x: u8, + subsampling_y: u8, + separate_uv_delta_q: u8, + color_range: ColorRange, + OrderHintBits: u8, + num_ticks_per_picture_minus_1: u64, + time_scale: u32, + num_units_in_display_tick: u32, + buffer_delay_length_minus_1: u8, + num_units_in_decoding_tick: u32, + buffer_removal_time_length_minus_1: u8, + frame_presentation_time_length_minus_1: u8, + initial_display_delay_minus_1: [MAX_OPERATING_POINTS]u8, + decoder_buffer_delay: [MAX_OPERATING_POINTS]u64, + encoder_buffer_delay: [MAX_OPERATING_POINTS]u64, + low_delay_mode_flag: [MAX_OPERATING_POINTS]bool, + operating_point_idc_arr: [MAX_OPERATING_POINTS]u16, + seq_level_idx: [MAX_OPERATING_POINTS]u8, + seq_tier: [MAX_OPERATING_POINTS]u8, + decoder_model_present_for_this_op: [MAX_OPERATING_POINTS]bool, + initial_display_delay_present_for_this_op: [MAX_OPERATING_POINTS]bool, + frame_id_numbers_present_flag: bool, + additional_frame_id_length_minus_1: u8, + delta_frame_id_length_minus_2: u8, + reduced_still_picture_header: bool, + equal_picture_interval: bool, +} + +FrameHeader :: struct { + SeenFrameHeader: bool, + TileNum: u64, + show_existing_frame: bool, +} + +read_obu :: proc(r: ^Reader, seq_header: ^SequenceHeader, frame_header: ^FrameHeader) -> (err: Error) { header := read_bitfield(r, OBUHeader) or_return size: u64 @@ -116,15 +210,14 @@ read_obu :: proc(r: ^Reader) -> (err: Error) { size = u64(r.box.size - BOX_HEADER_SIZE - 1 - u32(header.obu_extension_flag)) } - // TODO: get bit position - //start_pos := get_position() + start_pos := r.i * 8 + i64(r.bits_read_in_byte) //// TODO: //if header.obu_type != .SEQUENCE_HEADER && header.obu_type != .TEMPORAL_DELIMITER && OperatingPointIdc != 0 && header.obu_extension_flag == 1 { - // in_temporal_layer := (OperatingPointIdc >> temporal_id) & 1 - // in_spatial_layer := (OperatingPointIdc >> (spatial_id + 8)) & 1 + // inTemporalLayer := (OperatingPointIdc >> temporal_id) & 1 + // inSpatialLayer := (OperatingPointIdc >> (spatial_id + 8)) & 1 - // if in_temporal_layer == 0 || in_spatial_layer == 0 { + // if inTemporalLayer == 0 || inSpatialLayer == 0 { // drop_obu() // return // } @@ -148,186 +241,208 @@ read_obu :: proc(r: ^Reader) -> (err: Error) { case .TEMPORAL_DELIMITER: // do nothing. the temporal OBU has an empty payload case .SEQUENCE_HEADER: - parse_sequence_header_obu(r) + parse_sequence_header_obu(r, seq_header) + fmt.println(seq_header) + case .FRAME_HEADER: + parse_frame_header_obu(r, size, seq_header, frame_header) case .FRAME: - // TODO: + parse_frame_obu(r, size, seq_header, frame_header) } - // TODO: - //current_pos := get_position() - //payload_bits := current_pos - start_pos + current_pos := r.i * 8 + i64(r.bits_read_in_byte) + payload_bits := current_pos - start_pos - //if size > 0 && header.obu_type != .TILE_GROUP && header.obu_type != .TILE_LIST && header.obu_type != .FRAME { - // trailing_bits(size * 8 - payload_bits) - //} + fmt.println("start pos", start_pos) + fmt.println("current pos", current_pos) + fmt.println("payload_bits", payload_bits) + fmt.println("trailing bits", size * 8 - u64(payload_bits)) + + if size > 0 && header.obu_type != .TILE_GROUP && header.obu_type != .TILE_LIST && header.obu_type != .FRAME { + trailing_bits(r, size * 8 - u64(payload_bits)) + } return nil } -//timing_info :: proc(r: ^Reader) { -// num_units_in_display_tick = f(r, 32) -// time_scale = f(r, 32) -// equal_picture_interval = f(r, 32) -// if equal_picture_interval == 1 { -// num_ticks_per_picture_minus_1 = uvlc(r) -// } -//} -// -//decoder_model_info :: proc(r: ^Reader) { -// buffer_delay_length_minus_1 = f(r, 5) -// num_units_in_decoding_tick = f(r, 32) -// buffer_removal_time_length_minus_1 = f(r, 5) -// frame_presentation_time_length_minus_1 = f(r, 5) -//} -// -//operating_parameters_info :: proc(r: ^Reader, op: u8) { -// n = buffer_delay_length_minus_1 + 1 -// decoder_buffer_delay[op] = f(r, n) -// encoder_buffer_delay[op] = f(r, n) -// low_delay_mode_flag[op] = f(r, 1) -//} -// -//color_config :: proc(r: ^Reader) { -// high_bitdepth = f(r, 1) -// -// if seq_profile == 2 && high_bitdepth == 1 { -// twelve_bit = f(r, 1) -// BitDepth = twelve_bit == 1 ? 12 : 10 -// } else if seq_profile <= 2 { -// BitDepth = high_bitdepth == 1 ? 10 : 8 -// } -// -// if seq_profile == 1 { -// mono_chrome = 0 -// } else { -// mono_chrome = f(r, 1) -// } -// -// num_planes = mono_chrome == 1 ? 1 : 3 -// color_description_present_flag = f(r, 1) -// -// if color_description_present_flag == 1 { -// color_primaries = auto_cast f(r, 8) -// transfer_characteristic = auto_cast f(r, 8) -// matrix_coefficients = auto_cast f(r, 8) -// } else { -// color_primaries = .UNSPECIFIED -// transfer_characteristic = .UNSPECIFIED -// matrix_coefficients = .UNSPECIFIED -// } -// -// if mono_chrome == 1 { -// color_range = f(r, 1) -// subsampling_x = 1 -// subsampling_y = 1 -// chroma_sample_position = .UNKNOWN -// separate_uv_delta_q = 0 -// return -// } else if color_primaries == .BT_709 && transfer_characteristic == .SRGB && matrix_coefficients == .IDENTITY { -// color_range = 1 -// subsampling_x = 0 -// subsampling_y = 0 -// } else { -// color_range = f(r, 1) -// -// if seq_profile == 0 { -// subsampling_x = 1 -// subsampling_y = 1 -// } else if seq_profile == 1 { -// subsampling_x = 0 -// subsampling_y = 0 -// } else { -// if BitDepth == 12 { -// subsampling_x = f(r, 1) -// -// if subsampling_x == 1 { -// subsampling_y = f(r, 1) -// } else { -// subsampling_y = 0 -// } -// } else { -// subsampling_x = 1 -// subsampling_y = 0 -// } -// } -// -// if subsampling_x == 1 && subsampling_y == 1 { -// chroma_sample_position = auto_cast f(r, 2) -// } -// } -// -// separate_uv_delta_q = f(r, 1) -//} +trailing_bits :: proc(r: ^Reader, nbits: u64) { + nbits := nbits + trailing_one_bit := f(r, 1) + nbits -= 1 -parse_sequence_header_obu :: proc(r: ^Reader) { + for nbits > 0 { + trailing_one_bit = f(r, 1) + nbits -= 1 + } +} + +timing_info :: proc(r: ^Reader, seq_header: ^SequenceHeader) { + seq_header.num_units_in_display_tick = auto_cast f(r, 32) + seq_header.time_scale = auto_cast f(r, 32) + seq_header.equal_picture_interval = auto_cast f(r, 32) + if seq_header.equal_picture_interval { + seq_header.num_ticks_per_picture_minus_1 = uvlc(r) + } +} + +decoder_model_info :: proc(r: ^Reader, seq_header: ^SequenceHeader) { + seq_header.buffer_delay_length_minus_1 = auto_cast f(r, 5) + seq_header.num_units_in_decoding_tick = auto_cast f(r, 32) + seq_header.buffer_removal_time_length_minus_1 = auto_cast f(r, 5) + seq_header.frame_presentation_time_length_minus_1 = auto_cast f(r, 5) +} + +operating_parameters_info :: proc(r: ^Reader, op: u8, seq_header: ^SequenceHeader) { + n := seq_header.buffer_delay_length_minus_1 + 1 + seq_header.decoder_buffer_delay[op] = f(r, auto_cast n) + seq_header.encoder_buffer_delay[op] = f(r, auto_cast n) + seq_header.low_delay_mode_flag[op] = auto_cast f(r, 1) +} + +color_config :: proc(r: ^Reader, seq_header: ^SequenceHeader) { + high_bitdepth := bool(f(r, 1)) + + if seq_header.seq_profile == 2 && high_bitdepth { + twelve_bit := bool(f(r, 1)) + seq_header.BitDepth = twelve_bit ? 12 : 10 + } else if seq_header.seq_profile <= 2 { + seq_header.BitDepth = high_bitdepth ? 10 : 8 + } + + if seq_header.seq_profile == 1 { + seq_header.mono_chrome = false + } else { + seq_header.mono_chrome = auto_cast f(r, 1) + } + + seq_header.num_planes = seq_header.mono_chrome ? 1 : 3 + color_description_present_flag: bool = auto_cast f(r, 1) + + if color_description_present_flag { + seq_header.color_primaries = auto_cast f(r, 8) + seq_header.transfer_characteristic = auto_cast f(r, 8) + seq_header.matrix_coefficients = auto_cast f(r, 8) + } else { + seq_header.color_primaries = .UNSPECIFIED + seq_header.transfer_characteristic = .UNSPECIFIED + seq_header.matrix_coefficients = .UNSPECIFIED + } + + if seq_header.mono_chrome { + seq_header.color_range = auto_cast f(r, 1) + seq_header.subsampling_x = 1 + seq_header.subsampling_y = 1 + seq_header.chroma_sample_position = .UNKNOWN + seq_header.separate_uv_delta_q = 0 + return + } else if seq_header.color_primaries == .BT_709 && seq_header.transfer_characteristic == .SRGB && seq_header.matrix_coefficients == .IDENTITY { + seq_header.color_range = .FULL + seq_header.subsampling_x = 0 + seq_header.subsampling_y = 0 + } else { + seq_header.color_range = auto_cast f(r, 1) + + if seq_header.seq_profile == 0 { + seq_header.subsampling_x = 1 + seq_header.subsampling_y = 1 + } else if seq_header.seq_profile == 1 { + seq_header.subsampling_x = 0 + seq_header.subsampling_y = 0 + } else { + if seq_header.BitDepth == 12 { + seq_header.subsampling_x = auto_cast f(r, 1) + + if seq_header.subsampling_x == 1 { + seq_header.subsampling_y = auto_cast f(r, 1) + } else { + seq_header.subsampling_y = 0 + } + } else { + seq_header.subsampling_x = 1 + seq_header.subsampling_y = 0 + } + } + + if seq_header.subsampling_x == 1 && seq_header.subsampling_y == 1 { + seq_header.chroma_sample_position = auto_cast f(r, 2) + } + } + + seq_header.separate_uv_delta_q = auto_cast f(r, 1) +} + +parse_sequence_header_obu :: proc(r: ^Reader, seq_header: ^SequenceHeader) -> (OBUError) { seq_profile := f(r, 3) - still_picture := f(r, 1) - reduced_still_picture_header := f(r, 1) + if seq_profile > 2 { + return .ReservedSeqProfile + } - timing_info_present_flag: u8 - decoder_model_info_present_flag: u8 - initial_display_delay_present_flag: u8 + still_picture := f(r, 1) + seq_header.reduced_still_picture_header := auto_cast f(r, 1) + + timing_info_present_flag: bool + decoder_model_info_present_flag: bool + initial_display_delay_present_flag: bool operating_points_cnt_minus_1: u8 - if reduced_still_picture_header == 1 { + if seq_header.reduced_still_picture_header { // TODO: should these be saved as state ?? - timing_info_present_flag = 0 - decoder_model_info_present_flag = 0 - initial_display_delay_present_flag = 0 + timing_info_present_flag = false + decoder_model_info_present_flag = false + initial_display_delay_present_flag = false operating_points_cnt_minus_1 = 0 - //operating_point_idc[ 0 ] = 0 - //seq_level_idx[ 0 ] - //seq_tier[ 0 ] = 0 - //decoder_model_present_for_this_op[ 0 ] = 0 - //initial_display_delay_present_for_this_op[ 0 ] = 0 + seq_header.operating_point_idc_arr[0] = 0 + seq_header.seq_level_idx[0] = auto_cast f(r, 5) + seq_header.seq_tier[0] = 0 + seq_header.decoder_model_present_for_this_op[0] = false + seq_header.initial_display_delay_present_for_this_op[0] = false } else { - //timing_info_present_flag = auto_cast f(r, 1) + timing_info_present_flag = auto_cast f(r, 1) - //if timing_info_present_flag == 1 { - // timing_info(r) + if timing_info_present_flag { + timing_info(r, seq_header) - // decoder_model_info_present_flag = auto_cast f(r, 1) - // if decoder_model_info_present_flag == 1 { - // decoder_model_info(r) - // } - //} else { - // decoder_model_info_present_flag = 0 - //} + decoder_model_info_present_flag = auto_cast f(r, 1) + if decoder_model_info_present_flag { + decoder_model_info(r, seq_header) + } + } else { + decoder_model_info_present_flag = false + } - //initial_display_delay_present_flag = auto_cast f(r, 1) - //operating_points_cnt_minus_1 = auto_cast f(r, 5) + initial_display_delay_present_flag = auto_cast f(r, 1) + operating_points_cnt_minus_1 = auto_cast f(r, 5) - //for i in 0 ..=operating_points_cnt_minus_1 { - // operating_point_idc[i] = f(r, 12) - // seq_level_idx[i] = f(r, 5) + for i in 0 ..=operating_points_cnt_minus_1 { + seq_header.operating_point_idc_arr[i] = auto_cast f(r, 12) + seq_header.seq_level_idx[i] = auto_cast f(r, 5) - // if seq_level_idx[i] > 7 { - // seq_tier[i] = f(r, 1) - // } else { - // seq_tier[i] = 0 - // } + if seq_header.seq_level_idx[i] > 7 { + seq_header.seq_tier[i] = auto_cast f(r, 1) + } else { + seq_header.seq_tier[i] = 0 + } - // if decoder_model_info_present_flag == 1 { - // decoder_model_present_for_this_op[i] = f(r, 1) - // if decoder_model_present_for_this_op[i] == 1 { - // operating_parameters_info(r, i) - // } - // } else { - // decoder_model_present_for_this_op[i] = 0 - // } + if decoder_model_info_present_flag { + seq_header.decoder_model_present_for_this_op[i] = auto_cast f(r, 1) + if seq_header.decoder_model_present_for_this_op[i] { + operating_parameters_info(r, i, seq_header) + } + } else { + seq_header.decoder_model_present_for_this_op[i] = false + } - // if initial_display_delay_present_flag == 1 { - // initial_display_delay_present_for_this_op[i] = f(r, 1) - // if initial_display_delay_present_for_this_op[i] == 1 { - // initial_display_delay_minus_1[i] = f(r, 4) - // } - // } - //} + if initial_display_delay_present_flag { + seq_header.initial_display_delay_present_for_this_op[i] = auto_cast f(r, 1) + if seq_header.initial_display_delay_present_for_this_op[i] { + seq_header.initial_display_delay_minus_1[i] = auto_cast f(r, 4) + } + } + } } fmt.println("seq_profile:", seq_profile) fmt.println("still_picture:", still_picture) - fmt.println("reduced_still_picture_header:", reduced_still_picture_header) + fmt.println("reduced_still_picture_header:", seq_header.reduced_still_picture_header) fmt.println("timing_info_present_flag:", timing_info_present_flag) fmt.println("decoder_model_info_present_flag:", decoder_model_info_present_flag) @@ -335,7 +450,7 @@ parse_sequence_header_obu :: proc(r: ^Reader) { fmt.println("operating_points_cnt_minus_1:", operating_points_cnt_minus_1) //operating_point := choose_operating_point() - //operating_point_idc_one := operating_point_idc[operating_point] + //operating_point_idc := seq_header.operating_point_idc_arr[operating_point] frame_width_bits_minus_1 := f(r, 4) frame_height_bits_minus_1 := f(r, 4) n := frame_width_bits_minus_1 + 1 @@ -343,19 +458,15 @@ parse_sequence_header_obu :: proc(r: ^Reader) { n = frame_height_bits_minus_1 + 1 max_frame_height_minus_1 := f(r, auto_cast n) - frame_id_numbers_present_flag: u8 - delta_frame_id_length_minus_2: u8 - additional_frame_id_length_minus_1: u8 - - if reduced_still_picture_header == 1 { - frame_id_numbers_present_flag = 0 + if seq_header.reduced_still_picture_header { + seq_header.frame_id_numbers_present_flag = false } else { - frame_id_numbers_present_flag = auto_cast f(r, 1) + seq_header.frame_id_numbers_present_flag = auto_cast f(r, 1) } - if frame_id_numbers_present_flag == 1 { - delta_frame_id_length_minus_2 = auto_cast f(r, 4) - additional_frame_id_length_minus_1 = auto_cast f(r, 3) + if seq_header.frame_id_numbers_present_flag { + seq_header.delta_frame_id_length_minus_2 = auto_cast f(r, 4) + seq_header.additional_frame_id_length_minus_1 = auto_cast f(r, 3) } use_128x128_superblock := f(r, 1) @@ -367,70 +478,479 @@ parse_sequence_header_obu :: proc(r: ^Reader) { fmt.println("max_frame_width_minus_1:", max_frame_width_minus_1) fmt.println("max_frame_height_minus_1:", max_frame_height_minus_1) - fmt.println("frame_id_numbers_present_flag:", frame_id_numbers_present_flag) - fmt.println("delta_frame_id_length_minus_2:", delta_frame_id_length_minus_2) - fmt.println("additional_frame_id_length_minus_1:", additional_frame_id_length_minus_1) + fmt.println("frame_id_numbers_present_flag:", seq_header.frame_id_numbers_present_flag) + fmt.println("delta_frame_id_length_minus_2:", seq_header.delta_frame_id_length_minus_2) + fmt.println("additional_frame_id_length_minus_1:", seq_header.additional_frame_id_length_minus_1) fmt.println("use_128x128_superblock:", use_128x128_superblock) fmt.println("enable_filter_intra:", enable_filter_intra) fmt.println("enable_intra_edge_filter:", enable_intra_edge_filter) - //if reduced_still_picture_header == 1 { - // enable_interintra_compound = 0 - // enable_masked_compound = 0 - // enable_warped_motion = 0 - // enable_dual_filter = 0 - // enable_order_hint = 0 - // enable_jnt_comp = 0 - // enable_ref_frame_mvs = 0 - // seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS - // seq_force_integer_mv = SELECT_INTEGER_MV - // OrderHintBits = 0 - //} else { - // enable_interintra_compount = f(r, 1) - // enable_masked_compound = f(r, 1) - // enable_warped_motion = f(r, 1) - // enable_dual_filter = f(r, 1) - // enable_order_hint = f(r, 1) - // if enable_order_hint == 1 { - // enable_jnt_comp = f(r, 1) - // enable_ref_frame_mvs = f(r, 1) - // } else { - // enable_jnt_comp = 0 - // enable_ref_frame_mvs = 0 - // } + enable_interintra_compound: u8 + enable_masked_compound: u8 + enable_warped_motion: u8 + enable_dual_filter: u8 + enable_order_hint: bool + enable_jnt_comp: u8 + enable_ref_frame_mvs: u8 + seq_force_screen_content_tools: u8 + seq_force_integer_mv: u8 - // seq_choose_screen_content_tools = f(r, 1) - // if seq_choose_screen_content_tools == 1 { - // seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS - // } else { - // seq_force_screen_content_tools = f(r, 1) - // } + if seq_header.reduced_still_picture_header { + enable_interintra_compound = 0 + enable_masked_compound = 0 + enable_warped_motion = 0 + enable_dual_filter = 0 + enable_order_hint = false + enable_jnt_comp = 0 + enable_ref_frame_mvs = 0 + seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS + seq_force_integer_mv = SELECT_INTEGER_MV + seq_header.OrderHintBits = 0 + } else { + enable_interintra_compound = auto_cast f(r, 1) + enable_masked_compound = auto_cast f(r, 1) + enable_warped_motion = auto_cast f(r, 1) + enable_dual_filter = auto_cast f(r, 1) + enable_order_hint = auto_cast f(r, 1) + if enable_order_hint { + enable_jnt_comp = auto_cast f(r, 1) + enable_ref_frame_mvs = auto_cast f(r, 1) + } else { + enable_jnt_comp = 0 + enable_ref_frame_mvs = 0 + } - // if seq_force_screen_content_tools > 0 { - // seq_choose_integer_mv = f(r, 1) - // if seq_choose_integer_mv == 1 { - // seq_force_integer_mv = SELECT_INTEGER_MV - // } else { - // seq_force_integer_mv = f(r, 1) - // } - // } else { - // seq_force_integer_mv = SELECT_INTEGER_MV - // } + seq_choose_screen_content_tools: bool = auto_cast f(r, 1) + if seq_choose_screen_content_tools { + seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS + } else { + seq_force_screen_content_tools = auto_cast f(r, 1) + } - // if enable_order_hint == 1 { - // order_hint_bits_minus_1 = f(r, 3) - // OrderHintBits = order_hint_bits_minus_1 + 1 - // } else { - // OrderHintBits = 0 - // } - //} + if seq_force_screen_content_tools > 0 { + seq_choose_integer_mv: bool = auto_cast f(r, 1) + if seq_choose_integer_mv { + seq_force_integer_mv = SELECT_INTEGER_MV + } else { + seq_force_integer_mv = auto_cast f(r, 1) + } + } else { + seq_force_integer_mv = SELECT_INTEGER_MV + } - //enable_superres = f(r, 1) - //enable_cdef = f(r, 1) - //enable_restoration = f(r, 1) - //color_config() - //film_grain_params_present = f(r, 1) + if enable_order_hint { + order_hint_bits_minus_1 := f(r, 3) + seq_header.OrderHintBits = u8(order_hint_bits_minus_1) + 1 + } else { + seq_header.OrderHintBits = 0 + } + } + + seq_header.enable_superres = auto_cast f(r, 1) + seq_header.enable_cdef = auto_cast f(r, 1) + seq_header.enable_restoration = auto_cast f(r, 1) + color_config(r, seq_header) + seq_header.film_grain_params_present = auto_cast f(r, 1) + + return nil +} + +byte_alignment :: proc(r: ^Reader) { + pos := r.i * 8 + i64(r.bits_read_in_byte) + for pos & 7 == 1 { + f(r, 1) + } +} + +parse_frame_obu :: proc(r: ^Reader, size: u64, seq_header: ^SequenceHeader, frame_header: ^FrameHeader) { + size := size + + start_bit_pos := r.i * 8 + i64(r.bits_read_in_byte) + parse_frame_header_obu(r, seq_header, frame_header) + byte_alignment(r) + end_bit_pos := r.i * 8 + i64(r.bits_read_in_byte) + header_bytes := (end_bit_pos - start_bit_pos) / 8 + size -= u64(header_bytes) + parse_tile_group_obu(r, size) +} + +uncompressed_header :: proc(r: ^Reader, seq_header: ^SequenceHeader, frame_header: ^FrameHeader) { + if seq_header.frame_id_numbers_present_flag { + idLen := seq_header.additional_frame_id_length_minus_1 + seq_header.delta_frame_id_length_minus_2 + 3 + } + + allFrames := (1 << NUM_REF_FRAMES) - 1 + if seq_header.reduced_still_picture_header { + frame_header.show_existing_frame = false + frame_type = .KEY_FRAME + FrameIsIntra = true + show_frame = true + showable_frame = false + } else { + frame_header.show_existing_frame = auto_cast f(r, 1) + if frame_header.show_existing_frame { + frame_to_show_map_idx = f(r, 3) + if seq_header.decoder_model_info_present_flag && !seq_header.equal_picture_interval { + temporal_point_info() + } + + refresh_frame_flags = 0 + + if seq_header.frame_id_numbers_present_flag { + display_frame_id = f(r, idLen) + } + + frame_type = RefFrameType[frame_to_show_map_idx] + if frame_type == .KEY_FRAME { + refresh_frame_flags = allFrames + } + if seq_header.film_grain_params_present { + load_grain_params(frame_to_show_map_idx) + } + return + } + + frame_type = f(r, 2) + FrameIsIntra = frame_type == .INTRA_ONLY_FRAME || frame_type == .KEY_FRAME + show_frame = f(r, 1) + + if show_frame && seq_header.decoder_model_info_present_flag && !seq_header.equal_picture_interval { + temporal_point_info() + } + + if show_frame { + showable_frame = frame_type != .KEY_FRAME + } else { + showable_frame = f(r, 1) + } + + if frame_type == .SWITCH_FRAME || (frame_type == .KEY_FRAME && show_frame) { + error_resilient_mode = 1 + } else { + error_resilient_mode = f(r, 1) + } + } + + if frame_type == .KEY_FRAME && show_frame { + for i in 0..> temporal_id) & 1 + inSpatialLayer = (opPtIdc >> (spatial_id + 8)) & 1 + if opPtIdc == 0 || (inTemporalLayer && inSpatialLayer) { + n = buffer_removal_time_length_minus_1 + 1 + buffer_removal_time[opNum] + } + } + } + } + } + + allow_high_precision_mv = 0 + use_ref_frame_mvs = 0 + allow_intrabc = 0 + + if frame_type == .SWITCH_FRAME || (frame_type == .KEY_FRAME && show_frame) { + refresh_frame_flags = allFrames + } else { + refresh_frame_flags = f(r, 8) + } + + if !FrameIsIntra || refresh_frame_flags != allFrames { + if error_resilient_mode && enable_order_hint { + for i in 0.. 0 + } + } + } + + if reduced_still_picture_header || disable_cdf_update { + disable_frame_end_update_cdf = 1 + } else { + disable_frame_end_update_cdf = f(r, 1) + } + + if primary_ref_frame == PRIMARY_REF_NONE { + init_non_coeff_cdfs() + setup_past_independence() + } else { + load_cdfs(ref_frame_idx[primary_ref_frame]) + load_previous() + } + + if use_ref_frame_mvs == 1 { + motion_field_estimation() + } + + tile_info() + quantization_params() + segmentation_params() + delta_q_params() + delta_lf_params() + + if primary_ref_frame == PRIMARY_REF_NONE { + init_coeff_cdfs() + } else { + load_previous_segment_ids() + } + + CodedLoseless = 1 + + for segmentId in 0.. 1 { + tile_start_and_end_present_flags = auto_cast f(r, 1) + } + + if NumTiles == 1 || !tile_start_and_end_present_flags { + tg_start = 0 + tg_end = NumTiles - 1 + } else { + tile_bits = TileColsLog2 + TileRowsLog2 + tg_start = f(r, tile_bits) + tg_end = f(r, tile_bits) + } + byte_alignment(r) + + end_bit_pos := r.i * 8 + r.bits_read_in_byte + header_bytes := (end_bit_pos - start_bit_pos) / 8 + size -= header_bytes + + for TileNum = tg_start; TileNum <= tg_end; TileNum+=1 { + tile_row := TileNum / TileCols + tile_col := TileNum % TileCols + last_tile := TileNum == tg_end + if last_tile { + tile_size = size + } else { + tile_size_minus_1 := le(TileSizeBytes) + tile_size = tile_size_minus_1 + 1 + size -= tile_size + TileSizeBytes + } + + MiRowStart = MiRowStarts[tileRow] + MiRowEnd = MiRowStarts[tileRow + 1] + MiColStart = MiColStarts[tileCol] + MiColEnd = MiColStarts[tileCol + 1] + CurrentQIndex = base_q_idx + init_symbol(tile_size) + decode_tile() + exit_symbol() + } + + if tg_end == TileNum - 1 { + if !disable_frame_end_update_cdf { + frame_end_update_cdf() + } + + decode_frame_wrapup() + seen_frame_header = false + } } f :: proc(r: ^Reader, n: int) -> u64 { @@ -479,3 +999,14 @@ uvlc :: proc(r: ^Reader) -> u64 { value := f(r, auto_cast leading_zeros) return value + (1 << leading_zeros) - 1 } + +le :: proc(r: ^Reader, n: int) -> u64 { + t := 0 + + for i in 0..