Loading libraries/scrcpy/src/codec/h265.spec.ts +197 −0 Original line number Diff line number Diff line Loading @@ -357,5 +357,202 @@ describe("h265", () => { sps_extension_data_flag: undefined, } satisfies ReturnType<typeof h265ParseSequenceParameterSet>); }); it("issue #732", () => { const buffer = new Uint8Array([ 66, 1, 3, 1, 96, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 150, 0, 0, 160, 2, 28, 128, 9, 33, 99, 107, 92, 146, 41, 187, 226, 170, 151, 43, 182, 64, ]); const sps = h265ParseSequenceParameterSet(buffer); assert.deepStrictEqual(sps, { sps_video_parameter_set_id: 4, sps_max_sub_layers_minus1: 1, sps_temporal_id_nesting_flag: false, profileTierLevel: { generalProfileTier: { profile_space: 0, tier_flag: false, profile_idc: 1, profileCompatibilitySet: new Uint8Array([3, 1, 96, 0]), profile_compatibility_flag: [ false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, ], constraintSet: new Uint8Array([0, 0, 0, 0, 0, 0]), progressive_source_flag: false, interlaced_source_flag: false, non_packed_constraint_flag: false, frame_only_constraint_flag: false, max_12bit_constraint_flag: false, max_10bit_constraint_flag: false, max_8bit_constraint_flag: false, max_422chroma_constraint_flag: false, max_420chroma_constraint_flag: false, max_monochrome_constraint_flag: false, intra_constraint_flag: false, one_picture_only_constraint_flag: false, lower_bit_rate_constraint_flag: false, max_14bit_constraint_flag: undefined, inbld_flag: false, }, general_level_idc: 0, sub_layer_profile_present_flag: [false], sub_layer_level_present_flag: [false], subLayerProfileTier: [], sub_layer_level_idc: [], }, sps_seq_parameter_set_id: 81923, chroma_format_idc: 6, separate_colour_plane_flag: undefined, pic_width_in_luma_samples: 3, pic_height_in_luma_samples: 583, conformance_window_flag: false, conf_win_left_offset: undefined, conf_win_right_offset: undefined, conf_win_top_offset: undefined, conf_win_bottom_offset: undefined, bit_depth_luma_minus8: 0, bit_depth_chroma_minus8: 2, log2_max_pic_order_cnt_lsb_minus4: 12, sps_sub_layer_ordering_info_present_flag: true, sps_max_dec_pic_buffering_minus1: [1, 1], sps_max_num_reorder_pics: [0, 0], sps_max_latency_increase_plus1: [0, 0], log2_min_luma_coding_block_size_minus3: 0, log2_diff_max_min_luma_coding_block_size: 3, log2_min_luma_transform_block_size_minus2: 0, log2_diff_max_min_luma_transform_block_size: 3, max_transform_hierarchy_depth_inter: 1, max_transform_hierarchy_depth_intra: 0, scaling_list_enabled_flag: false, sps_scaling_list_data_present_flag: undefined, scalingListData: undefined, amp_enabled_flag: false, sample_adaptive_offset_enabled_flag: true, pcm_enabled_flag: true, pcm_sample_bit_depth_luma_minus1: 7, pcm_sample_bit_depth_chroma_minus1: 7, log2_min_pcm_luma_coding_block_size_minus3: 0, log2_diff_max_min_pcm_luma_coding_block_size: 0, pcm_loop_filter_disabled_flag: false, num_short_term_ref_pic_sets: 4, shortTermRefPicSets: [ { stRpsIdx: 0, num_short_term_ref_pic_sets: 4, inter_ref_pic_set_prediction_flag: false, delta_idx_minus1: 0, delta_rps_sign: false, abs_delta_rps_minus1: 0, used_by_curr_pic_flag: [], use_delta_flag: [], num_negative_pics: 1, num_positive_pics: 0, delta_poc_s0_minus1: [1], used_by_curr_pic_s0_flag: [true], delta_poc_s1_minus1: [], used_by_curr_pic_s1_flag: [], }, { stRpsIdx: 1, num_short_term_ref_pic_sets: 4, inter_ref_pic_set_prediction_flag: false, delta_idx_minus1: 0, delta_rps_sign: false, abs_delta_rps_minus1: 0, used_by_curr_pic_flag: [], use_delta_flag: [], num_negative_pics: 1, num_positive_pics: 0, delta_poc_s0_minus1: [0], used_by_curr_pic_s0_flag: [true], delta_poc_s1_minus1: [], used_by_curr_pic_s1_flag: [], }, { stRpsIdx: 2, num_short_term_ref_pic_sets: 4, inter_ref_pic_set_prediction_flag: false, delta_idx_minus1: 0, delta_rps_sign: false, abs_delta_rps_minus1: 0, used_by_curr_pic_flag: [], use_delta_flag: [], num_negative_pics: 1, num_positive_pics: 0, delta_poc_s0_minus1: [2], used_by_curr_pic_s0_flag: [true], delta_poc_s1_minus1: [], used_by_curr_pic_s1_flag: [], }, { stRpsIdx: 3, num_short_term_ref_pic_sets: 4, inter_ref_pic_set_prediction_flag: false, delta_idx_minus1: 0, delta_rps_sign: false, abs_delta_rps_minus1: 0, used_by_curr_pic_flag: [], use_delta_flag: [], num_negative_pics: 0, num_positive_pics: 0, delta_poc_s0_minus1: [], used_by_curr_pic_s0_flag: [], delta_poc_s1_minus1: [], used_by_curr_pic_s1_flag: [], }, ], long_term_ref_pics_present_flag: false, num_long_term_ref_pics_sps: undefined, lt_ref_pic_poc_lsb_sps: undefined, used_by_curr_pic_lt_sps_flag: undefined, sps_temporal_mvp_enabled_flag: true, strong_intra_smoothing_enabled_flag: true, vui_parameters_present_flag: false, vuiParameters: undefined, sps_extension_present_flag: false, sps_range_extension_flag: undefined, sps_multilayer_extension_flag: undefined, sps_3d_extension_flag: undefined, sps_scc_extension_flag: undefined, sps_extension_4bits: undefined, spsMultilayerExtension: undefined, sps3dExtension: undefined, sps_extension_data_flag: undefined, } satisfies ReturnType<typeof h265ParseSequenceParameterSet>); }); }); }); libraries/scrcpy/src/codec/h265.ts +31 −5 Original line number Diff line number Diff line Loading @@ -330,8 +330,10 @@ export function h265ParseSequenceParameterSet(nalu: Uint8Array) { if (pcm_enabled_flag) { pcm_sample_bit_depth_luma_minus1 = reader.read(4); pcm_sample_bit_depth_chroma_minus1 = reader.read(4); log2_min_pcm_luma_coding_block_size_minus3 = reader.read(4); log2_diff_max_min_pcm_luma_coding_block_size = reader.read(4); log2_min_pcm_luma_coding_block_size_minus3 = reader.decodeExponentialGolombNumber(); log2_diff_max_min_pcm_luma_coding_block_size = reader.decodeExponentialGolombNumber(); pcm_loop_filter_disabled_flag = !!reader.next(); } Loading Loading @@ -894,6 +896,30 @@ export function h265ParseShortTermReferencePictureSet( }; } export const H265AspectRatioIndicator = { Unspecified: 0, Square: 1, _12_11: 2, _10_11: 3, _16_11: 4, _40_33: 5, _24_11: 6, _20_11: 7, _32_11: 8, _80_33: 9, _18_11: 10, _15_11: 11, _64_33: 12, _160_99: 13, _4_3: 15, _3_2: 16, _2_1: 17, Extended: 255, } as const; export type H265AspectRatioIndicator = (typeof H265AspectRatioIndicator)[keyof typeof H265AspectRatioIndicator]; /** * E.2.1 VUI parameters syntax */ Loading @@ -902,12 +928,12 @@ export function h265ParseVuiParameters( sps_max_sub_layers_minus1: number, ) { const aspect_ratio_info_present_flag = !!reader.next(); let aspect_ratio_idc: number | undefined; let aspect_ratio_idc: H265AspectRatioIndicator | undefined; let sar_width: number | undefined; let sar_height: number | undefined; if (aspect_ratio_info_present_flag) { aspect_ratio_idc = reader.read(8); if (aspect_ratio_idc === 255) { aspect_ratio_idc = reader.read(8) as H265AspectRatioIndicator; if (aspect_ratio_idc === H265AspectRatioIndicator.Extended) { sar_width = reader.read(16); sar_height = reader.read(16); } Loading Loading
libraries/scrcpy/src/codec/h265.spec.ts +197 −0 Original line number Diff line number Diff line Loading @@ -357,5 +357,202 @@ describe("h265", () => { sps_extension_data_flag: undefined, } satisfies ReturnType<typeof h265ParseSequenceParameterSet>); }); it("issue #732", () => { const buffer = new Uint8Array([ 66, 1, 3, 1, 96, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 150, 0, 0, 160, 2, 28, 128, 9, 33, 99, 107, 92, 146, 41, 187, 226, 170, 151, 43, 182, 64, ]); const sps = h265ParseSequenceParameterSet(buffer); assert.deepStrictEqual(sps, { sps_video_parameter_set_id: 4, sps_max_sub_layers_minus1: 1, sps_temporal_id_nesting_flag: false, profileTierLevel: { generalProfileTier: { profile_space: 0, tier_flag: false, profile_idc: 1, profileCompatibilitySet: new Uint8Array([3, 1, 96, 0]), profile_compatibility_flag: [ false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, ], constraintSet: new Uint8Array([0, 0, 0, 0, 0, 0]), progressive_source_flag: false, interlaced_source_flag: false, non_packed_constraint_flag: false, frame_only_constraint_flag: false, max_12bit_constraint_flag: false, max_10bit_constraint_flag: false, max_8bit_constraint_flag: false, max_422chroma_constraint_flag: false, max_420chroma_constraint_flag: false, max_monochrome_constraint_flag: false, intra_constraint_flag: false, one_picture_only_constraint_flag: false, lower_bit_rate_constraint_flag: false, max_14bit_constraint_flag: undefined, inbld_flag: false, }, general_level_idc: 0, sub_layer_profile_present_flag: [false], sub_layer_level_present_flag: [false], subLayerProfileTier: [], sub_layer_level_idc: [], }, sps_seq_parameter_set_id: 81923, chroma_format_idc: 6, separate_colour_plane_flag: undefined, pic_width_in_luma_samples: 3, pic_height_in_luma_samples: 583, conformance_window_flag: false, conf_win_left_offset: undefined, conf_win_right_offset: undefined, conf_win_top_offset: undefined, conf_win_bottom_offset: undefined, bit_depth_luma_minus8: 0, bit_depth_chroma_minus8: 2, log2_max_pic_order_cnt_lsb_minus4: 12, sps_sub_layer_ordering_info_present_flag: true, sps_max_dec_pic_buffering_minus1: [1, 1], sps_max_num_reorder_pics: [0, 0], sps_max_latency_increase_plus1: [0, 0], log2_min_luma_coding_block_size_minus3: 0, log2_diff_max_min_luma_coding_block_size: 3, log2_min_luma_transform_block_size_minus2: 0, log2_diff_max_min_luma_transform_block_size: 3, max_transform_hierarchy_depth_inter: 1, max_transform_hierarchy_depth_intra: 0, scaling_list_enabled_flag: false, sps_scaling_list_data_present_flag: undefined, scalingListData: undefined, amp_enabled_flag: false, sample_adaptive_offset_enabled_flag: true, pcm_enabled_flag: true, pcm_sample_bit_depth_luma_minus1: 7, pcm_sample_bit_depth_chroma_minus1: 7, log2_min_pcm_luma_coding_block_size_minus3: 0, log2_diff_max_min_pcm_luma_coding_block_size: 0, pcm_loop_filter_disabled_flag: false, num_short_term_ref_pic_sets: 4, shortTermRefPicSets: [ { stRpsIdx: 0, num_short_term_ref_pic_sets: 4, inter_ref_pic_set_prediction_flag: false, delta_idx_minus1: 0, delta_rps_sign: false, abs_delta_rps_minus1: 0, used_by_curr_pic_flag: [], use_delta_flag: [], num_negative_pics: 1, num_positive_pics: 0, delta_poc_s0_minus1: [1], used_by_curr_pic_s0_flag: [true], delta_poc_s1_minus1: [], used_by_curr_pic_s1_flag: [], }, { stRpsIdx: 1, num_short_term_ref_pic_sets: 4, inter_ref_pic_set_prediction_flag: false, delta_idx_minus1: 0, delta_rps_sign: false, abs_delta_rps_minus1: 0, used_by_curr_pic_flag: [], use_delta_flag: [], num_negative_pics: 1, num_positive_pics: 0, delta_poc_s0_minus1: [0], used_by_curr_pic_s0_flag: [true], delta_poc_s1_minus1: [], used_by_curr_pic_s1_flag: [], }, { stRpsIdx: 2, num_short_term_ref_pic_sets: 4, inter_ref_pic_set_prediction_flag: false, delta_idx_minus1: 0, delta_rps_sign: false, abs_delta_rps_minus1: 0, used_by_curr_pic_flag: [], use_delta_flag: [], num_negative_pics: 1, num_positive_pics: 0, delta_poc_s0_minus1: [2], used_by_curr_pic_s0_flag: [true], delta_poc_s1_minus1: [], used_by_curr_pic_s1_flag: [], }, { stRpsIdx: 3, num_short_term_ref_pic_sets: 4, inter_ref_pic_set_prediction_flag: false, delta_idx_minus1: 0, delta_rps_sign: false, abs_delta_rps_minus1: 0, used_by_curr_pic_flag: [], use_delta_flag: [], num_negative_pics: 0, num_positive_pics: 0, delta_poc_s0_minus1: [], used_by_curr_pic_s0_flag: [], delta_poc_s1_minus1: [], used_by_curr_pic_s1_flag: [], }, ], long_term_ref_pics_present_flag: false, num_long_term_ref_pics_sps: undefined, lt_ref_pic_poc_lsb_sps: undefined, used_by_curr_pic_lt_sps_flag: undefined, sps_temporal_mvp_enabled_flag: true, strong_intra_smoothing_enabled_flag: true, vui_parameters_present_flag: false, vuiParameters: undefined, sps_extension_present_flag: false, sps_range_extension_flag: undefined, sps_multilayer_extension_flag: undefined, sps_3d_extension_flag: undefined, sps_scc_extension_flag: undefined, sps_extension_4bits: undefined, spsMultilayerExtension: undefined, sps3dExtension: undefined, sps_extension_data_flag: undefined, } satisfies ReturnType<typeof h265ParseSequenceParameterSet>); }); }); });
libraries/scrcpy/src/codec/h265.ts +31 −5 Original line number Diff line number Diff line Loading @@ -330,8 +330,10 @@ export function h265ParseSequenceParameterSet(nalu: Uint8Array) { if (pcm_enabled_flag) { pcm_sample_bit_depth_luma_minus1 = reader.read(4); pcm_sample_bit_depth_chroma_minus1 = reader.read(4); log2_min_pcm_luma_coding_block_size_minus3 = reader.read(4); log2_diff_max_min_pcm_luma_coding_block_size = reader.read(4); log2_min_pcm_luma_coding_block_size_minus3 = reader.decodeExponentialGolombNumber(); log2_diff_max_min_pcm_luma_coding_block_size = reader.decodeExponentialGolombNumber(); pcm_loop_filter_disabled_flag = !!reader.next(); } Loading Loading @@ -894,6 +896,30 @@ export function h265ParseShortTermReferencePictureSet( }; } export const H265AspectRatioIndicator = { Unspecified: 0, Square: 1, _12_11: 2, _10_11: 3, _16_11: 4, _40_33: 5, _24_11: 6, _20_11: 7, _32_11: 8, _80_33: 9, _18_11: 10, _15_11: 11, _64_33: 12, _160_99: 13, _4_3: 15, _3_2: 16, _2_1: 17, Extended: 255, } as const; export type H265AspectRatioIndicator = (typeof H265AspectRatioIndicator)[keyof typeof H265AspectRatioIndicator]; /** * E.2.1 VUI parameters syntax */ Loading @@ -902,12 +928,12 @@ export function h265ParseVuiParameters( sps_max_sub_layers_minus1: number, ) { const aspect_ratio_info_present_flag = !!reader.next(); let aspect_ratio_idc: number | undefined; let aspect_ratio_idc: H265AspectRatioIndicator | undefined; let sar_width: number | undefined; let sar_height: number | undefined; if (aspect_ratio_info_present_flag) { aspect_ratio_idc = reader.read(8); if (aspect_ratio_idc === 255) { aspect_ratio_idc = reader.read(8) as H265AspectRatioIndicator; if (aspect_ratio_idc === H265AspectRatioIndicator.Extended) { sar_width = reader.read(16); sar_height = reader.read(16); } Loading