1 Star 0 Fork 0

general252/gomedia

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
h265.go 35.03 KB
一键复制 编辑 原始数据 按行查看 历史
西门小小 提交于 2023-05-09 20:31 . fix #75 #74 skip garbage bytes
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
package codec
import (
"bytes"
"errors"
)
// nal_unit_header() {
// forbidden_zero_bit f(1)
// nal_unit_type u(6)
// nuh_layer_id u(6)
// nuh_temporal_id_plus1 u(3)
// }
type H265NaluHdr struct {
Forbidden_zero_bit uint8
Nal_unit_type uint8
Nuh_layer_id uint8
Nuh_temporal_id_plus1 uint8
}
func (hdr *H265NaluHdr) Decode(bs *BitStream) {
hdr.Forbidden_zero_bit = bs.GetBit()
hdr.Nal_unit_type = bs.Uint8(6)
hdr.Nuh_layer_id = bs.Uint8(6)
hdr.Nuh_temporal_id_plus1 = bs.Uint8(3)
}
type VPS struct {
Vps_video_parameter_set_id uint8
Vps_base_layer_internal_flag uint8
Vps_base_layer_available_flag uint8
Vps_max_layers_minus1 uint8
Vps_max_sub_layers_minus1 uint8
Vps_temporal_id_nesting_flag uint8
Vps_reserved_0xffff_16bits uint16
Ptl ProfileTierLevel
Vps_sub_layer_ordering_info_present_flag uint8
Vps_max_dec_pic_buffering_minus1 [8]uint64
Vps_max_num_reorder_pics [8]uint64
Vps_max_latency_increase_plus1 [8]uint64
Vps_max_layer_id uint8
Vps_num_layer_sets_minus1 uint64
Layer_id_included_flag [][]uint8
Vps_timing_info_present_flag uint8
TimeInfo VPSTimeInfo
// Vps_extension_flag uint8
}
type VPSTimeInfo struct {
Vps_num_units_in_tick uint32
Vps_time_scale uint32
Vps_poc_proportional_to_timing_flag uint8
Vps_num_ticks_poc_diff_one_minus1 uint64
Vps_num_hrd_parameters uint64
Hrd_layer_set_idx []uint64
Cprms_present_flag []uint8
}
type ProfileTierLevel struct {
General_profile_space uint8
General_tier_flag uint8
General_profile_idc uint8
General_profile_compatibility_flag uint32
General_constraint_indicator_flag uint64
General_level_idc uint8
Sub_layer_profile_present_flag [8]uint8
Sub_layer_level_present_flag [8]uint8
}
//nalu without startcode
func (vps *VPS) Decode(nalu []byte) {
sodb := CovertRbspToSodb(nalu)
bs := NewBitStream(sodb)
hdr := H265NaluHdr{}
hdr.Decode(bs)
vps.Vps_video_parameter_set_id = bs.Uint8(4)
vps.Vps_base_layer_internal_flag = bs.Uint8(1)
vps.Vps_base_layer_available_flag = bs.Uint8(1)
vps.Vps_max_layers_minus1 = bs.Uint8(6)
vps.Vps_max_sub_layers_minus1 = bs.Uint8(3)
vps.Vps_temporal_id_nesting_flag = bs.Uint8(1)
vps.Vps_reserved_0xffff_16bits = bs.Uint16(16)
vps.Ptl = Profile_tier_level(1, vps.Vps_max_sub_layers_minus1, bs)
vps.Vps_sub_layer_ordering_info_present_flag = bs.Uint8(1)
var i int
if vps.Vps_sub_layer_ordering_info_present_flag > 0 {
i = 0
} else {
i = int(vps.Vps_max_sub_layers_minus1)
}
for ; i <= int(vps.Vps_max_sub_layers_minus1); i++ {
vps.Vps_max_dec_pic_buffering_minus1[i] = bs.ReadUE()
vps.Vps_max_num_reorder_pics[i] = bs.ReadUE()
vps.Vps_max_latency_increase_plus1[i] = bs.ReadUE()
}
vps.Vps_max_layer_id = bs.Uint8(6)
vps.Vps_num_layer_sets_minus1 = bs.ReadUE()
vps.Layer_id_included_flag = make([][]uint8, vps.Vps_num_layer_sets_minus1)
for i := 1; i <= int(vps.Vps_num_layer_sets_minus1); i++ {
vps.Layer_id_included_flag[i] = make([]uint8, vps.Vps_max_layer_id)
for j := 0; j <= int(vps.Vps_max_layer_id); j++ {
vps.Layer_id_included_flag[i][j] = bs.Uint8(1)
}
}
vps.Vps_timing_info_present_flag = bs.Uint8(1)
if vps.Vps_timing_info_present_flag == 1 {
vps.TimeInfo = ParserVPSTimeinfo(bs)
}
}
//ffmpeg hevc.c
//static void hvcc_parse_ptl(GetBitContext *gb,HEVCDecoderConfigurationRecord *hvcc,unsigned int max_sub_layers_minus1)
func Profile_tier_level(profilePresentFlag uint8, maxNumSubLayersMinus1 uint8, bs *BitStream) ProfileTierLevel {
var ptl ProfileTierLevel
ptl.General_profile_space = bs.Uint8(2)
ptl.General_tier_flag = bs.Uint8(1)
ptl.General_profile_idc = bs.Uint8(5)
ptl.General_profile_compatibility_flag = bs.Uint32(32)
ptl.General_constraint_indicator_flag = bs.GetBits(48)
ptl.General_level_idc = bs.Uint8(8)
for i := 0; i < int(maxNumSubLayersMinus1); i++ {
ptl.Sub_layer_profile_present_flag[i] = bs.GetBit()
ptl.Sub_layer_level_present_flag[i] = bs.GetBit()
}
if maxNumSubLayersMinus1 > 0 {
for i := maxNumSubLayersMinus1; i < 8; i++ {
bs.SkipBits(2)
}
}
for i := 0; i < int(maxNumSubLayersMinus1); i++ {
if ptl.Sub_layer_profile_present_flag[i] == 1 {
/*
* sub_layer_profile_space[i] u(2)
* sub_layer_tier_flag[i] u(1)
* sub_layer_profile_idc[i] u(5)
* sub_layer_profile_compatibility_flag[i][0..31] u(32)
* sub_layer_progressive_source_flag[i] u(1)
* sub_layer_interlaced_source_flag[i] u(1)
* sub_layer_non_packed_constraint_flag[i] u(1)
* sub_layer_frame_only_constraint_flag[i] u(1)
* sub_layer_reserved_zero_44bits[i] u(44)
*/
bs.SkipBits(88)
}
if ptl.Sub_layer_level_present_flag[i] == 1 {
bs.SkipBits(8)
}
}
return ptl
}
func ParserVPSTimeinfo(bs *BitStream) VPSTimeInfo {
var ti VPSTimeInfo
ti.Vps_num_units_in_tick = bs.Uint32(32)
ti.Vps_time_scale = bs.Uint32(32)
ti.Vps_poc_proportional_to_timing_flag = bs.Uint8(1)
if ti.Vps_poc_proportional_to_timing_flag == 1 {
ti.Vps_num_ticks_poc_diff_one_minus1 = bs.ReadUE()
}
ti.Vps_num_hrd_parameters = bs.ReadUE()
// for i := 0; i < int(ti.Vps_num_hrd_parameters); i++ {
// ti.Hrd_layer_set_idx[i] = bs.ReadUE()
// if i > 0 {
// ti.Cprms_present_flag[i] = bs.Uint8(1)
// }
// //Hrd_parameters(ti.Cprms_present_flag[i])
// }
return ti
}
type H265RawSPS struct {
Sps_video_parameter_set_id uint8
Sps_max_sub_layers_minus1 uint8
Sps_temporal_id_nesting_flag uint8
Ptl ProfileTierLevel
Sps_seq_parameter_set_id uint64
Chroma_format_idc uint64
Pic_width_in_luma_samples uint64
Pic_height_in_luma_samples uint64
Conformance_window_flag uint8
Conf_win_left_offset uint64
Conf_win_right_offset uint64
Conf_win_top_offset uint64
Conf_win_bottom_offset uint64
Bit_depth_luma_minus8 uint64
Bit_depth_chroma_minus8 uint64
Log2_max_pic_order_cnt_lsb_minus4 uint64
Sps_sub_layer_ordering_info_present_flag uint8
Vui_parameters_present_flag uint8
Vui VUI_Parameters
}
//nalu without startcode
func (sps *H265RawSPS) Decode(nalu []byte) {
sodb := CovertRbspToSodb(nalu)
bs := NewBitStream(sodb)
hdr := H265NaluHdr{}
hdr.Decode(bs)
sps.Sps_video_parameter_set_id = bs.Uint8(4)
sps.Sps_max_sub_layers_minus1 = bs.Uint8(3)
sps.Sps_temporal_id_nesting_flag = bs.Uint8(1)
sps.Ptl = Profile_tier_level(1, sps.Sps_max_sub_layers_minus1, bs)
sps.Sps_seq_parameter_set_id = bs.ReadUE()
sps.Chroma_format_idc = bs.ReadUE()
if sps.Chroma_format_idc == 3 {
bs.SkipBits(1)
}
sps.Pic_width_in_luma_samples = bs.ReadUE()
sps.Pic_height_in_luma_samples = bs.ReadUE()
sps.Conformance_window_flag = bs.Uint8(1)
if sps.Conformance_window_flag == 1 {
sps.Conf_win_left_offset = bs.ReadUE()
sps.Conf_win_right_offset = bs.ReadUE()
sps.Conf_win_top_offset = bs.ReadUE()
sps.Conf_win_bottom_offset = bs.ReadUE()
}
sps.Bit_depth_luma_minus8 = bs.ReadUE()
sps.Bit_depth_chroma_minus8 = bs.ReadUE()
sps.Log2_max_pic_order_cnt_lsb_minus4 = bs.ReadUE()
sps.Sps_sub_layer_ordering_info_present_flag = bs.Uint8(1)
i := 0
if sps.Sps_sub_layer_ordering_info_present_flag == 0 {
i = int(sps.Sps_max_sub_layers_minus1)
}
for ; i <= int(sps.Sps_max_sub_layers_minus1); i++ {
bs.ReadUE()
bs.ReadUE()
bs.ReadUE()
}
bs.ReadUE() // log2_min_luma_coding_block_size_minus3
bs.ReadUE() // log2_diff_max_min_luma_coding_block_size
bs.ReadUE() // log2_min_transform_block_size_minus2
bs.ReadUE() // log2_diff_max_min_transform_block_size
bs.ReadUE() // max_transform_hierarchy_depth_inter
bs.ReadUE() // max_transform_hierarchy_depth_intra
scaling_list_enabled_flag := bs.GetBit()
if scaling_list_enabled_flag > 0 {
sps_scaling_list_data_present_flag := bs.GetBit()
if sps_scaling_list_data_present_flag > 0 {
scaling_list_data(bs)
}
}
bs.SkipBits(1)
bs.SkipBits(1)
if bs.GetBit() == 1 {
bs.GetBits(4)
bs.GetBits(4)
bs.ReadUE()
bs.ReadUE()
bs.GetBit()
}
num_short_term_ref_pic_sets := bs.ReadUE()
if num_short_term_ref_pic_sets > 64 {
panic("beyond HEVC_MAX_SHORT_TERM_REF_PIC_SETS")
}
var num_delta_pocs [64]uint32
for i := 0; i < int(num_short_term_ref_pic_sets); i++ {
parse_rps(i, num_short_term_ref_pic_sets, num_delta_pocs, bs)
}
if bs.GetBit() == 1 {
num_long_term_ref_pics_sps := bs.ReadUE()
for i := 0; i < int(num_long_term_ref_pics_sps); i++ {
length := Min(int(sps.Log2_max_pic_order_cnt_lsb_minus4+4), 16)
bs.SkipBits(length)
bs.SkipBits(1)
}
}
bs.SkipBits(1)
bs.SkipBits(1)
sps.Vui_parameters_present_flag = bs.GetBit()
if sps.Vui_parameters_present_flag == 1 {
sps.Vui.Decode(bs, sps.Sps_max_sub_layers_minus1)
}
}
type VUI_Parameters struct {
Aspect_ratio_info_present_flag uint8
Overscan_info_present_flag uint8
Chroma_loc_info_present_flag uint8
Neutral_chroma_indication_flag uint8
Field_seq_flag uint8
Frame_field_info_present_flag uint8
Default_display_window_flag uint8
Vui_timing_info_present_flag uint8
Vui_num_units_in_tick uint32
Vui_time_scale uint32
Vui_poc_proportional_to_timing_flag uint8
Vui_hrd_parameters_present_flag uint8
Bitstream_restriction_flag uint8
Tiles_fixed_structure_flag uint8
Motion_vectors_over_pic_boundaries_flag uint8
Restricted_ref_pic_lists_flag uint8
Min_spatial_segmentation_idc uint64
Max_bytes_per_pic_denom uint64
Max_bits_per_min_cu_denom uint64
Log2_max_mv_length_horizontal uint64
Log2_max_mv_length_vertical uint64
}
func (vui *VUI_Parameters) Decode(bs *BitStream, max_sub_layers_minus1 uint8) {
vui.Aspect_ratio_info_present_flag = bs.Uint8(1)
if vui.Aspect_ratio_info_present_flag == 1 {
if bs.Uint8(8) == 255 {
bs.SkipBits(32)
}
}
vui.Overscan_info_present_flag = bs.Uint8(1)
if vui.Overscan_info_present_flag == 1 {
bs.SkipBits(1)
}
if bs.GetBit() == 1 {
bs.SkipBits(4)
if bs.GetBit() == 1 {
bs.SkipBits(24)
}
}
vui.Chroma_loc_info_present_flag = bs.GetBit()
if vui.Chroma_loc_info_present_flag == 1 {
bs.ReadUE()
bs.ReadUE()
}
vui.Neutral_chroma_indication_flag = bs.GetBit()
vui.Field_seq_flag = bs.GetBit()
vui.Frame_field_info_present_flag = bs.GetBit()
vui.Default_display_window_flag = bs.GetBit()
if vui.Default_display_window_flag == 1 {
bs.ReadUE()
bs.ReadUE()
bs.ReadUE()
bs.ReadUE()
}
vui.Vui_timing_info_present_flag = bs.GetBit()
if vui.Vui_timing_info_present_flag == 1 {
vui.Vui_num_units_in_tick = bs.Uint32(32)
vui.Vui_time_scale = bs.Uint32(32)
vui.Vui_poc_proportional_to_timing_flag = bs.GetBit()
if vui.Vui_poc_proportional_to_timing_flag == 1 {
bs.ReadUE()
}
vui.Vui_hrd_parameters_present_flag = bs.GetBit()
if vui.Vui_hrd_parameters_present_flag == 1 {
skip_hrd_parameters(1, uint32(max_sub_layers_minus1), bs)
}
}
vui.Bitstream_restriction_flag = bs.GetBit()
if vui.Bitstream_restriction_flag == 1 {
vui.Tiles_fixed_structure_flag = bs.GetBit()
vui.Motion_vectors_over_pic_boundaries_flag = bs.GetBit()
vui.Restricted_ref_pic_lists_flag = bs.GetBit()
vui.Min_spatial_segmentation_idc = bs.ReadUE()
vui.Max_bytes_per_pic_denom = bs.ReadUE()
vui.Max_bits_per_min_cu_denom = bs.ReadUE()
vui.Log2_max_mv_length_horizontal = bs.ReadUE()
vui.Log2_max_mv_length_vertical = bs.ReadUE()
}
}
func skip_hrd_parameters(cprms_present_flag uint8, max_sub_layers_minus1 uint32, bs *BitStream) {
nal_hrd_parameters_present_flag := uint8(0)
vcl_hrd_parameters_present_flag := uint8(0)
sub_pic_hrd_params_present_flag := uint8(0)
if cprms_present_flag == 1 {
nal_hrd_parameters_present_flag = bs.GetBit()
vcl_hrd_parameters_present_flag = bs.GetBit()
if nal_hrd_parameters_present_flag == 1 || vcl_hrd_parameters_present_flag == 1 {
sub_pic_hrd_params_present_flag = bs.GetBit()
if sub_pic_hrd_params_present_flag == 1 {
/*
* tick_divisor_minus2 u(8)
* du_cpb_removal_delay_increment_length_minus1 u(5)
* sub_pic_cpb_params_in_pic_timing_sei_flag u(1)
* dpb_output_delay_du_length_minus1 u(5)
*/
bs.SkipBits(19)
}
bs.SkipBits(8)
if sub_pic_hrd_params_present_flag == 1 {
// cpb_size_du_scale
bs.SkipBits(4)
}
/*
* initial_cpb_removal_delay_length_minus1 u(5)
* au_cpb_removal_delay_length_minus1 u(5)
* dpb_output_delay_length_minus1 u(5)
*/
bs.SkipBits(15)
}
}
for i := 0; i <= int(max_sub_layers_minus1); i++ {
fixed_pic_rate_general_flag := bs.GetBit()
fixed_pic_rate_within_cvs_flag := uint8(0)
low_delay_hrd_flag := uint8(0)
cpb_cnt_minus1 := uint32(0)
if fixed_pic_rate_general_flag == 0 {
fixed_pic_rate_within_cvs_flag = bs.GetBit()
}
if fixed_pic_rate_within_cvs_flag == 1 {
bs.ReadUE()
} else {
low_delay_hrd_flag = bs.GetBit()
}
if low_delay_hrd_flag == 0 {
cpb_cnt_minus1 = uint32(bs.ReadUE())
if cpb_cnt_minus1 > 31 {
panic("cpb_cnt_minus1 > 31")
}
}
skip_sub_layer_hrd_parameters := func() {
for i := 0; i < int(cpb_cnt_minus1); i++ {
bs.ReadUE()
bs.ReadUE()
if sub_pic_hrd_params_present_flag == 1 {
bs.ReadUE()
bs.ReadUE()
}
bs.SkipBits(1)
}
}
if nal_hrd_parameters_present_flag == 1 {
skip_sub_layer_hrd_parameters()
}
if vcl_hrd_parameters_present_flag == 1 {
skip_sub_layer_hrd_parameters()
}
}
}
func scaling_list_data(bs *BitStream) {
for i := 0; i < 4; i++ {
maxj := 6
if i == 3 {
maxj = 2
}
for j := 0; j < maxj; j++ {
if bs.GetBit() == 0 {
bs.ReadUE()
} else {
num_coeffs := Min(64, 1<<(4+(i<<1)))
if i > 1 {
bs.ReadSE()
}
for k := 0; k < num_coeffs; k++ {
bs.ReadSE()
}
}
}
}
}
func parse_rps(rps_idx int, nums_rps uint64, num_delta_pocs [64]uint32, bs *BitStream) {
if rps_idx > 0 && bs.GetBit() > 0 {
if rps_idx > int(nums_rps) {
panic("rps_idx > int(nums_rps)")
}
bs.SkipBits(1)
bs.ReadUE()
num_delta_pocs[rps_idx] = 0
for i := uint32(0); i <= num_delta_pocs[rps_idx-1]; i++ {
var use_delta_flag uint8
var used_by_curr_pic_flag uint8 = bs.GetBit()
if used_by_curr_pic_flag == 0 {
use_delta_flag = bs.GetBit()
}
if use_delta_flag > 0 || used_by_curr_pic_flag > 0 {
num_delta_pocs[rps_idx]++
}
}
} else {
num_negative_pics := bs.ReadUE()
num_positive_pics := bs.ReadUE()
if (num_negative_pics+num_positive_pics)*2 > uint64(bs.RemainBits()) {
panic("(num_negative_pics + num_positive_pics) * 2> uint64(bs.RemainBits())")
}
for i := 0; i < int(num_negative_pics); i++ {
bs.ReadUE()
bs.SkipBits(1)
}
for i := 0; i < int(num_positive_pics); i++ {
bs.ReadUE()
bs.SkipBits(1)
}
}
}
type H265RawPPS struct {
Pps_pic_parameter_set_id uint64
Pps_seq_parameter_set_id uint64
Dependent_slice_segments_enabled_flag uint8
Output_flag_present_flag uint8
Num_extra_slice_header_bits uint8
Sign_data_hiding_enabled_flag uint8
Cabac_init_present_flag uint8
Num_ref_idx_l0_default_active_minus1 uint64
Num_ref_idx_l1_default_active_minus1 uint64
Init_qp_minus26 int64
Constrained_intra_pred_flag uint8
Transform_skip_enabled_flag uint8
Cu_qp_delta_enabled_flag uint8
Diff_cu_qp_delta_depth uint64
Pps_cb_qp_offset int64
Pps_cr_qp_offset int64
Pps_slice_chroma_qp_offsets_present_flag uint8
Weighted_pred_flag uint8
Weighted_bipred_flag uint8
Transquant_bypass_enabled_flag uint8
Tiles_enabled_flag uint8
Entropy_coding_sync_enabled_flag uint8
}
//nalu without startcode
func (pps *H265RawPPS) Decode(nalu []byte) {
sodb := CovertRbspToSodb(nalu)
bs := NewBitStream(sodb)
hdr := H265NaluHdr{}
hdr.Decode(bs)
pps.Pps_pic_parameter_set_id = bs.ReadUE()
pps.Pps_seq_parameter_set_id = bs.ReadUE()
pps.Dependent_slice_segments_enabled_flag = bs.GetBit()
pps.Output_flag_present_flag = bs.GetBit()
pps.Num_extra_slice_header_bits = bs.Uint8(3)
pps.Sign_data_hiding_enabled_flag = bs.GetBit()
pps.Cabac_init_present_flag = bs.GetBit()
pps.Num_ref_idx_l0_default_active_minus1 = bs.ReadUE()
pps.Num_ref_idx_l1_default_active_minus1 = bs.ReadUE()
pps.Init_qp_minus26 = bs.ReadSE()
pps.Constrained_intra_pred_flag = bs.GetBit()
pps.Transform_skip_enabled_flag = bs.GetBit()
pps.Cu_qp_delta_enabled_flag = bs.GetBit()
if pps.Cu_qp_delta_enabled_flag == 1 {
pps.Diff_cu_qp_delta_depth = bs.ReadUE()
}
pps.Pps_cb_qp_offset = bs.ReadSE()
pps.Pps_cr_qp_offset = bs.ReadSE()
pps.Pps_slice_chroma_qp_offsets_present_flag = bs.GetBit()
pps.Weighted_pred_flag = bs.GetBit()
pps.Weighted_bipred_flag = bs.GetBit()
pps.Transquant_bypass_enabled_flag = bs.GetBit()
pps.Tiles_enabled_flag = bs.GetBit()
pps.Entropy_coding_sync_enabled_flag = bs.GetBit()
}
func GetH265Resolution(sps []byte) (width uint32, height uint32) {
start, sc := FindStartCode(sps, 0)
h265sps := H265RawSPS{}
h265sps.Decode(sps[start+int(sc):])
width = uint32(h265sps.Pic_width_in_luma_samples)
height = uint32(h265sps.Pic_height_in_luma_samples)
return
}
func GetVPSIdWithStartCode(vps []byte) uint8 {
start, sc := FindStartCode(vps, 0)
return GetVPSId(vps[start+int(sc):])
}
func GetVPSId(vps []byte) uint8 {
var rawvps VPS
rawvps.Decode(vps)
return rawvps.Vps_video_parameter_set_id
}
func GetH265SPSIdWithStartCode(sps []byte) uint64 {
start, sc := FindStartCode(sps, 0)
return GetH265SPSId(sps[start+int(sc):])
}
func GetH265SPSId(sps []byte) uint64 {
var rawsps H265RawSPS
rawsps.Decode(sps)
return rawsps.Sps_seq_parameter_set_id
}
func GetH265PPSIdWithStartCode(pps []byte) uint64 {
start, sc := FindStartCode(pps, 0)
return GetH265SPSId(pps[start+int(sc):])
}
func GetH265PPSId(pps []byte) uint64 {
var rawpps H265RawPPS
rawpps.Decode(pps)
return rawpps.Pps_pic_parameter_set_id
}
/*
ISO/IEC 14496-15:2017(E) 8.3.3.1.2 Syntax (p71)
aligned(8) class HEVCDecoderConfigurationRecord {
unsigned int(8) configurationVersion = 1;
unsigned int(2) general_profile_space;
unsigned int(1) general_tier_flag;
unsigned int(5) general_profile_idc;
unsigned int(32) general_profile_compatibility_flags;
unsigned int(48) general_constraint_indicator_flags;
unsigned int(8) general_level_idc;
bit(4) reserved = '1111'b;
unsigned int(12) min_spatial_segmentation_idc;
bit(6) reserved = '111111'b;
unsigned int(2) parallelismType;
bit(6) reserved = '111111'b;
unsigned int(2) chromaFormat;
bit(5) reserved = '11111'b;
unsigned int(3) bitDepthLumaMinus8;
bit(5) reserved = '11111'b;
unsigned int(3) bitDepthChromaMinus8;
bit(16) avgFrameRate;
bit(2) constantFrameRate;
bit(3) numTemporalLayers;
bit(1) temporalIdNested;
unsigned int(2) lengthSizeMinusOne;
unsigned int(8) numOfArrays;
for (j=0; j < numOfArrays; j++) {
bit(1) array_completeness;
unsigned int(1) reserved = 0;
unsigned int(6) NAL_unit_type;
unsigned int(16) numNalus;
for (i=0; i< numNalus; i++) {
unsigned int(16) nalUnitLength;
bit(8*nalUnitLength) nalUnit;
}
}
}
*/
type NalUnit struct {
NalUnitLength uint16
Nalu []byte
}
type HVCCNALUnitArray struct {
Array_completeness uint8
NAL_unit_type uint8
NumNalus uint16
NalUnits []*NalUnit
}
type HEVCRecordConfiguration struct {
ConfigurationVersion uint8
General_profile_space uint8
General_tier_flag uint8
General_profile_idc uint8
General_profile_compatibility_flags uint32
General_constraint_indicator_flags uint64
General_level_idc uint8
Min_spatial_segmentation_idc uint16
ParallelismType uint8
ChromaFormat uint8
BitDepthLumaMinus8 uint8
BitDepthChromaMinus8 uint8
AvgFrameRate uint16
ConstantFrameRate uint8
NumTemporalLayers uint8
TemporalIdNested uint8
LengthSizeMinusOne uint8
NumOfArrays uint8
Arrays []*HVCCNALUnitArray
}
func NewHEVCRecordConfiguration() *HEVCRecordConfiguration {
return &HEVCRecordConfiguration{
ConfigurationVersion: 1,
General_profile_compatibility_flags: 0xffffffff,
General_constraint_indicator_flags: 0xffffffffffffffff,
Min_spatial_segmentation_idc: 4097,
LengthSizeMinusOne: 3,
}
}
func (hvcc *HEVCRecordConfiguration) Encode() ([]byte, error) {
if len(hvcc.Arrays) < 3 {
return nil, errors.New("lack of sps or pps or vps")
}
bsw := NewBitStreamWriter(512)
bsw.PutByte(hvcc.ConfigurationVersion)
bsw.PutUint8(hvcc.General_profile_space, 2)
bsw.PutUint8(hvcc.General_tier_flag, 1)
bsw.PutUint8(hvcc.General_profile_idc, 5)
bsw.PutUint32(hvcc.General_profile_compatibility_flags, 32)
bsw.PutUint64(hvcc.General_constraint_indicator_flags, 48)
bsw.PutByte(hvcc.General_level_idc)
bsw.PutUint8(0x0F, 4)
bsw.PutUint16(hvcc.Min_spatial_segmentation_idc, 12)
bsw.PutUint8(0x3F, 6)
//ffmpeg hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc)
/*
* parallelismType indicates the type of parallelism that is used to meet
* the restrictions imposed by min_spatial_segmentation_idc when the value
* of min_spatial_segmentation_idc is greater than 0.
*/
if hvcc.Min_spatial_segmentation_idc == 0 {
hvcc.ParallelismType = 0
}
bsw.PutUint8(hvcc.ParallelismType, 2)
bsw.PutUint8(0x3F, 6)
bsw.PutUint8(hvcc.ChromaFormat, 2)
bsw.PutUint8(0x1F, 5)
bsw.PutUint8(hvcc.BitDepthLumaMinus8, 3)
bsw.PutUint8(0x1F, 5)
bsw.PutUint8(hvcc.BitDepthChromaMinus8, 3)
bsw.PutUint16(hvcc.AvgFrameRate, 16)
bsw.PutUint8(hvcc.ConstantFrameRate, 2)
bsw.PutUint8(hvcc.NumTemporalLayers, 3)
bsw.PutUint8(hvcc.TemporalIdNested, 1)
bsw.PutUint8(hvcc.LengthSizeMinusOne, 2)
bsw.PutByte(uint8(len(hvcc.Arrays)))
for _, arrays := range hvcc.Arrays {
bsw.PutUint8(arrays.Array_completeness, 1)
bsw.PutUint8(0, 1)
bsw.PutUint8(arrays.NAL_unit_type, 6)
bsw.PutUint16(uint16(len(arrays.NalUnits)), 16)
for _, nalu := range arrays.NalUnits {
bsw.PutUint16(nalu.NalUnitLength, 16)
bsw.PutBytes(nalu.Nalu)
}
}
return bsw.Bits(), nil
}
func (hvcc *HEVCRecordConfiguration) Decode(hevc []byte) {
bs := NewBitStream(hevc)
hvcc.ConfigurationVersion = bs.Uint8(8)
hvcc.General_profile_space = bs.Uint8(2)
hvcc.General_tier_flag = bs.Uint8(1)
hvcc.General_profile_idc = bs.Uint8(5)
hvcc.General_profile_compatibility_flags = bs.Uint32(32)
hvcc.General_constraint_indicator_flags = bs.GetBits(48)
hvcc.General_level_idc = bs.Uint8(8)
bs.SkipBits(4)
hvcc.Min_spatial_segmentation_idc = bs.Uint16(12)
bs.SkipBits(6)
hvcc.ParallelismType = bs.Uint8(2)
bs.SkipBits(6)
hvcc.ChromaFormat = bs.Uint8(2)
bs.SkipBits(5)
hvcc.BitDepthLumaMinus8 = bs.Uint8(3)
bs.SkipBits(5)
hvcc.BitDepthChromaMinus8 = bs.Uint8(3)
hvcc.AvgFrameRate = bs.Uint16(16)
hvcc.ConstantFrameRate = bs.Uint8(2)
hvcc.NumTemporalLayers = bs.Uint8(3)
hvcc.TemporalIdNested = bs.Uint8(1)
hvcc.LengthSizeMinusOne = bs.Uint8(2)
hvcc.NumOfArrays = bs.Uint8(8)
hvcc.Arrays = make([]*HVCCNALUnitArray, hvcc.NumOfArrays)
for i := 0; i < int(hvcc.NumOfArrays); i++ {
hvcc.Arrays[i] = new(HVCCNALUnitArray)
hvcc.Arrays[i].Array_completeness = bs.GetBit()
bs.SkipBits(1)
hvcc.Arrays[i].NAL_unit_type = bs.Uint8(6)
hvcc.Arrays[i].NumNalus = bs.Uint16(16)
hvcc.Arrays[i].NalUnits = make([]*NalUnit, hvcc.Arrays[i].NumNalus)
for j := 0; j < int(hvcc.Arrays[i].NumNalus); j++ {
hvcc.Arrays[i].NalUnits[j] = new(NalUnit)
hvcc.Arrays[i].NalUnits[j].NalUnitLength = bs.Uint16(16)
hvcc.Arrays[i].NalUnits[j].Nalu = bs.GetBytes(int(hvcc.Arrays[i].NalUnits[j].NalUnitLength))
}
}
}
func (hvcc *HEVCRecordConfiguration) UpdateSPS(sps []byte) {
start, sc := FindStartCode(sps, 0)
sps = sps[start+int(sc):]
var rawsps H265RawSPS
rawsps.Decode(sps)
spsid := rawsps.Sps_seq_parameter_set_id
var needUpdate bool = false
i := 0
for ; i < len(hvcc.Arrays); i++ {
arrays := hvcc.Arrays[i]
if arrays.NAL_unit_type != uint8(H265_NAL_SPS) {
continue
}
j := 0
for ; j < len(arrays.NalUnits); j++ {
if spsid != GetH265SPSId(arrays.NalUnits[j].Nalu) {
continue
}
//find the same sps nalu
if arrays.NalUnits[j].NalUnitLength == uint16(len(sps)) && bytes.Equal(arrays.NalUnits[j].Nalu, sps) {
return
}
tmpsps := make([]byte, len(sps))
copy(tmpsps, sps)
arrays.NalUnits[j].Nalu = tmpsps
arrays.NalUnits[j].NalUnitLength = uint16(len(tmpsps))
needUpdate = true
break
}
if j == len(arrays.NalUnits) {
nalu := &NalUnit{
Nalu: make([]byte, len(sps)),
NalUnitLength: uint16(len(sps)),
}
copy(nalu.Nalu, sps)
arrays.NalUnits = append(arrays.NalUnits, nalu)
needUpdate = true
}
break
}
if i == len(hvcc.Arrays) {
nua := &HVCCNALUnitArray{
Array_completeness: 1,
NAL_unit_type: 33,
NumNalus: 1,
NalUnits: make([]*NalUnit, 1),
}
nu := &NalUnit{
NalUnitLength: uint16(len(sps)),
Nalu: make([]byte, len(sps)),
}
copy(nu.Nalu, sps)
nua.NalUnits[0] = nu
hvcc.Arrays = append(hvcc.Arrays, nua)
needUpdate = true
}
if needUpdate {
hvcc.NumTemporalLayers = uint8(Max(int(hvcc.NumTemporalLayers), int(rawsps.Sps_max_sub_layers_minus1+1)))
hvcc.TemporalIdNested = rawsps.Sps_temporal_id_nesting_flag
hvcc.ChromaFormat = uint8(rawsps.Chroma_format_idc)
hvcc.BitDepthChromaMinus8 = uint8(rawsps.Bit_depth_chroma_minus8)
hvcc.BitDepthLumaMinus8 = uint8(rawsps.Bit_depth_luma_minus8)
hvcc.updatePtl(rawsps.Ptl)
hvcc.updateVui(rawsps.Vui)
}
}
func (hvcc *HEVCRecordConfiguration) UpdatePPS(pps []byte) {
start, sc := FindStartCode(pps, 0)
pps = pps[start+int(sc):]
var rawpps H265RawPPS
rawpps.Decode(pps)
ppsid := rawpps.Pps_pic_parameter_set_id
var needUpdate bool = false
i := 0
for ; i < len(hvcc.Arrays); i++ {
arrays := hvcc.Arrays[i]
if arrays.NAL_unit_type != uint8(H265_NAL_PPS) {
continue
}
j := 0
for ; j < len(arrays.NalUnits); j++ {
if ppsid != GetH265PPSId(arrays.NalUnits[j].Nalu) {
continue
}
//find the same sps nalu
if arrays.NalUnits[j].NalUnitLength == uint16(len(pps)) && bytes.Equal(arrays.NalUnits[j].Nalu, pps) {
return
}
tmppps := make([]byte, len(pps))
copy(tmppps, pps)
arrays.NalUnits[j].Nalu = tmppps
arrays.NalUnits[j].NalUnitLength = uint16(len(tmppps))
needUpdate = true
break
}
if j == len(arrays.NalUnits) {
nalu := &NalUnit{
Nalu: make([]byte, len(pps)),
NalUnitLength: uint16(len(pps)),
}
copy(nalu.Nalu, pps)
arrays.NalUnits = append(arrays.NalUnits, nalu)
needUpdate = true
}
break
}
if i == len(hvcc.Arrays) {
nua := &HVCCNALUnitArray{
Array_completeness: 1,
NAL_unit_type: 34,
NumNalus: 1,
NalUnits: make([]*NalUnit, 1),
}
nu := &NalUnit{
NalUnitLength: uint16(len(pps)),
Nalu: make([]byte, len(pps)),
}
copy(nu.Nalu, pps)
nua.NalUnits[0] = nu
hvcc.Arrays = append(hvcc.Arrays, nua)
needUpdate = true
}
if needUpdate {
if rawpps.Entropy_coding_sync_enabled_flag == 1 && rawpps.Tiles_enabled_flag == 1 {
hvcc.ParallelismType = 0
} else if rawpps.Entropy_coding_sync_enabled_flag == 1 {
hvcc.ParallelismType = 3
} else if rawpps.Tiles_enabled_flag == 1 {
hvcc.ParallelismType = 2
} else {
hvcc.ParallelismType = 1
}
}
}
func (hvcc *HEVCRecordConfiguration) UpdateVPS(vps []byte) {
start, sc := FindStartCode(vps, 0)
vps = vps[start+int(sc):]
var rawvps VPS
rawvps.Decode(vps)
vpsid := rawvps.Vps_video_parameter_set_id
var needUpdate bool = false
i := 0
for ; i < len(hvcc.Arrays); i++ {
arrays := hvcc.Arrays[i]
if arrays.NAL_unit_type != uint8(H265_NAL_VPS) {
continue
}
j := 0
for ; j < len(arrays.NalUnits); j++ {
if vpsid != GetVPSId(arrays.NalUnits[j].Nalu) {
continue
}
//find the same sps nalu
if arrays.NalUnits[j].NalUnitLength == uint16(len(vps)) && bytes.Equal(arrays.NalUnits[j].Nalu, vps) {
return
}
tmpvps := make([]byte, len(vps))
copy(tmpvps, vps)
arrays.NalUnits[j].Nalu = tmpvps
arrays.NalUnits[j].NalUnitLength = uint16(len(tmpvps))
needUpdate = true
break
}
if j == len(arrays.NalUnits) {
nalu := &NalUnit{
Nalu: make([]byte, len(vps)),
NalUnitLength: uint16(len(vps)),
}
copy(nalu.Nalu, vps)
arrays.NalUnits = append(arrays.NalUnits, nalu)
needUpdate = true
}
break
}
if i == len(hvcc.Arrays) {
nua := &HVCCNALUnitArray{
Array_completeness: 1,
NAL_unit_type: 32,
NumNalus: 1,
NalUnits: make([]*NalUnit, 1),
}
nu := &NalUnit{
NalUnitLength: uint16(len(vps)),
Nalu: make([]byte, len(vps)),
}
copy(nu.Nalu, vps)
nua.NalUnits[0] = nu
hvcc.Arrays = append(hvcc.Arrays, nua)
needUpdate = true
}
if needUpdate {
hvcc.NumTemporalLayers = uint8(Max(int(hvcc.NumTemporalLayers), int(rawvps.Vps_max_layers_minus1+1)))
hvcc.updatePtl(rawvps.Ptl)
}
}
func (hvcc *HEVCRecordConfiguration) ToNalus() (nalus []byte) {
startcode := []byte{0x00, 0x00, 0x00, 0x01}
for _, arrays := range hvcc.Arrays {
for _, unit := range arrays.NalUnits {
nalus = append(nalus, startcode...)
nalus = append(nalus, unit.Nalu[:unit.NalUnitLength]...)
}
}
return
}
func (hvcc *HEVCRecordConfiguration) updatePtl(ptl ProfileTierLevel) {
hvcc.General_profile_space = ptl.General_profile_space
if hvcc.General_tier_flag < ptl.General_tier_flag {
hvcc.General_level_idc = ptl.General_level_idc
} else {
hvcc.General_level_idc = uint8(Max(int(hvcc.General_level_idc), int(ptl.General_level_idc)))
}
hvcc.General_tier_flag = uint8(Max(int(hvcc.General_tier_flag), int(ptl.General_tier_flag)))
hvcc.General_profile_idc = uint8(Max(int(hvcc.General_profile_idc), int(ptl.General_profile_idc)))
hvcc.General_profile_compatibility_flags &= ptl.General_profile_compatibility_flag
hvcc.General_constraint_indicator_flags &= ptl.General_constraint_indicator_flag
}
func (hvcc *HEVCRecordConfiguration) updateVui(vui VUI_Parameters) {
hvcc.Min_spatial_segmentation_idc = uint16(Min(int(hvcc.Min_spatial_segmentation_idc), int(vui.Min_spatial_segmentation_idc)))
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/general252/gomedia.git
git@gitee.com:general252/gomedia.git
general252
gomedia
gomedia
v0.0.1

搜索帮助