fps
This commit is contained in:
		| @@ -3,6 +3,7 @@ package h264parser | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"math" | ||||
|  | ||||
| 	"github.com/deepch/vdk/av" | ||||
| 	"github.com/deepch/vdk/utils/bits" | ||||
| @@ -294,8 +295,10 @@ func SplitNALUs(b []byte) (nalus [][]byte, typ int) { | ||||
| } | ||||
|  | ||||
| type SPSInfo struct { | ||||
| 	ProfileIdc uint | ||||
| 	LevelIdc   uint | ||||
| 	Id                uint | ||||
| 	ProfileIdc        uint | ||||
| 	LevelIdc          uint | ||||
| 	ConstraintSetFlag uint | ||||
|  | ||||
| 	MbWidth  uint | ||||
| 	MbHeight uint | ||||
| @@ -307,38 +310,59 @@ type SPSInfo struct { | ||||
|  | ||||
| 	Width  uint | ||||
| 	Height uint | ||||
| 	FPS    uint | ||||
| } | ||||
|  | ||||
| func ParseSPS(data []byte) (self SPSInfo, err error) { | ||||
| func RemoveH264orH265EmulationBytes(b []byte) []byte { | ||||
| 	j := 0 | ||||
| 	r := make([]byte, len(b)) | ||||
| 	for i := 0; (i < len(b)) && (j < len(b)); { | ||||
| 		if i+2 < len(b) && | ||||
| 			b[i] == 0 && b[i+1] == 0 && b[i+2] == 3 { | ||||
| 			r[j] = 0 | ||||
| 			r[j+1] = 0 | ||||
| 			j = j + 2 | ||||
| 			i = i + 3 | ||||
| 		} else { | ||||
| 			r[j] = b[i] | ||||
| 			j = j + 1 | ||||
| 			i = i + 1 | ||||
| 		} | ||||
| 	} | ||||
| 	return r[:j] | ||||
| } | ||||
| func ParseSPS(data []byte) (s SPSInfo, err error) { | ||||
| 	data = RemoveH264orH265EmulationBytes(data) | ||||
| 	r := &bits.GolombBitReader{R: bytes.NewReader(data)} | ||||
|  | ||||
| 	if _, err = r.ReadBits(8); err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if self.ProfileIdc, err = r.ReadBits(8); err != nil { | ||||
| 	if s.ProfileIdc, err = r.ReadBits(8); err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// constraint_set0_flag-constraint_set6_flag,reserved_zero_2bits | ||||
| 	if _, err = r.ReadBits(8); err != nil { | ||||
| 	if s.ConstraintSetFlag, err = r.ReadBits(8); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	s.ConstraintSetFlag = s.ConstraintSetFlag >> 2 | ||||
|  | ||||
| 	// level_idc | ||||
| 	if self.LevelIdc, err = r.ReadBits(8); err != nil { | ||||
| 	if s.LevelIdc, err = r.ReadBits(8); err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// seq_parameter_set_id | ||||
| 	if _, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 	if s.Id, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if self.ProfileIdc == 100 || self.ProfileIdc == 110 || | ||||
| 		self.ProfileIdc == 122 || self.ProfileIdc == 244 || | ||||
| 		self.ProfileIdc == 44 || self.ProfileIdc == 83 || | ||||
| 		self.ProfileIdc == 86 || self.ProfileIdc == 118 { | ||||
| 	if s.ProfileIdc == 100 || s.ProfileIdc == 110 || | ||||
| 		s.ProfileIdc == 122 || s.ProfileIdc == 244 || | ||||
| 		s.ProfileIdc == 44 || s.ProfileIdc == 83 || | ||||
| 		s.ProfileIdc == 86 || s.ProfileIdc == 118 { | ||||
|  | ||||
| 		var chroma_format_idc uint | ||||
| 		if chroma_format_idc, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| @@ -450,15 +474,15 @@ func ParseSPS(data []byte) (self SPSInfo, err error) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if self.MbWidth, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 	if s.MbWidth, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	self.MbWidth++ | ||||
| 	s.MbWidth++ | ||||
|  | ||||
| 	if self.MbHeight, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 	if s.MbHeight, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	self.MbHeight++ | ||||
| 	s.MbHeight++ | ||||
|  | ||||
| 	var frame_mbs_only_flag uint | ||||
| 	if frame_mbs_only_flag, err = r.ReadBit(); err != nil { | ||||
| @@ -481,23 +505,146 @@ func ParseSPS(data []byte) (self SPSInfo, err error) { | ||||
| 		return | ||||
| 	} | ||||
| 	if frame_cropping_flag != 0 { | ||||
| 		if self.CropLeft, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 		if s.CropLeft, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if self.CropRight, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 		if s.CropRight, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if self.CropTop, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 		if s.CropTop, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if self.CropBottom, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 		if s.CropBottom, err = r.ReadExponentialGolombCode(); err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	self.Width = (self.MbWidth * 16) - self.CropLeft*2 - self.CropRight*2 | ||||
| 	self.Height = ((2 - frame_mbs_only_flag) * self.MbHeight * 16) - self.CropTop*2 - self.CropBottom*2 | ||||
| 	s.Width = (s.MbWidth * 16) - s.CropLeft*2 - s.CropRight*2 | ||||
| 	s.Height = ((2 - frame_mbs_only_flag) * s.MbHeight * 16) - s.CropTop*2 - s.CropBottom*2 | ||||
|  | ||||
| 	vui_parameter_present_flag, err := r.ReadBit() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if vui_parameter_present_flag != 0 { | ||||
| 		aspect_ratio_info_present_flag, err := r.ReadBit() | ||||
| 		if err != nil { | ||||
| 			return s, err | ||||
| 		} | ||||
|  | ||||
| 		if aspect_ratio_info_present_flag != 0 { | ||||
| 			aspect_ratio_idc, err := r.ReadBits(8) | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
|  | ||||
| 			if aspect_ratio_idc == 255 { | ||||
| 				sar_width, err := r.ReadBits(16) | ||||
| 				if err != nil { | ||||
| 					return s, err | ||||
| 				} | ||||
| 				sar_height, err := r.ReadBits(16) | ||||
| 				if err != nil { | ||||
| 					return s, err | ||||
| 				} | ||||
|  | ||||
| 				_, _ = sar_width, sar_height | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		overscan_info_present_flag, err := r.ReadBit() | ||||
| 		if err != nil { | ||||
| 			return s, err | ||||
| 		} | ||||
|  | ||||
| 		if overscan_info_present_flag != 0 { | ||||
| 			overscan_appropriate_flagu, err := r.ReadBit() | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
|  | ||||
| 			_ = overscan_appropriate_flagu | ||||
| 		} | ||||
| 		video_signal_type_present_flag, err := r.ReadBit() | ||||
| 		if video_signal_type_present_flag != 0 { | ||||
| 			video_format, err := r.ReadBits(3) | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
| 			_ = video_format | ||||
| 			video_full_range_flag, err := r.ReadBit() | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
| 			_ = video_full_range_flag | ||||
| 			colour_description_present_flag, err := r.ReadBit() | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
| 			if colour_description_present_flag != 0 { | ||||
| 				colour_primaries, err := r.ReadBits(8) | ||||
| 				if err != nil { | ||||
| 					return s, err | ||||
| 				} | ||||
| 				_ = colour_primaries | ||||
| 				transfer_characteristics, err := r.ReadBits(8) | ||||
| 				if err != nil { | ||||
| 					return s, err | ||||
| 				} | ||||
| 				_ = transfer_characteristics | ||||
| 				matrix_coefficients, err := r.ReadBits(8) | ||||
| 				if err != nil { | ||||
| 					return s, err | ||||
| 				} | ||||
| 				_ = matrix_coefficients | ||||
| 			} | ||||
| 		} | ||||
| 		chroma_loc_info_present_flag, err := r.ReadBit() | ||||
| 		if err != nil { | ||||
| 			return s, err | ||||
| 		} | ||||
| 		if chroma_loc_info_present_flag != 0 { | ||||
| 			chroma_sample_loc_type_top_field, err := r.ReadSE() | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
| 			_ = chroma_sample_loc_type_top_field | ||||
|  | ||||
| 			chroma_sample_loc_type_bottom_field, err := r.ReadSE() | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
|  | ||||
| 			_ = chroma_sample_loc_type_bottom_field | ||||
| 		} | ||||
|  | ||||
| 		timing_info_present_flag, err := r.ReadBit() | ||||
| 		if err != nil { | ||||
| 			return s, err | ||||
| 		} | ||||
|  | ||||
| 		if timing_info_present_flag != 0 { | ||||
| 			num_units_in_tick, err := r.ReadBits(32) | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
| 			time_scale, err := r.ReadBits(32) | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
| 			s.FPS = uint(math.Floor(float64(time_scale) / float64(num_units_in_tick) / 2.0)) | ||||
| 			fixed_frame_rate_flag, err := r.ReadBit() | ||||
| 			if err != nil { | ||||
| 				return s, err | ||||
| 			} | ||||
| 			if fixed_frame_rate_flag != 0 { | ||||
| 				//utils.L.InfoLn("fixed_frame_rate_flag", fixed_frame_rate_flag) | ||||
| 				//have been devide 2 | ||||
| 				//self.FPS = self.FPS / 2 | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Andrey Semochkin
					Andrey Semochkin