dtsestimator.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package common
  2. import "m7s.live/engine/v4/util"
  3. // DTSEstimator is a DTS estimator.
  4. type DTSEstimator struct {
  5. hasB bool
  6. prevPTS uint32
  7. prevDTS uint32
  8. cache []uint32
  9. interval uint32
  10. }
  11. // NewDTSEstimator allocates a DTSEstimator.
  12. func NewDTSEstimator() *DTSEstimator {
  13. result := &DTSEstimator{}
  14. return result
  15. }
  16. func (d *DTSEstimator) Clone() *DTSEstimator {
  17. return &DTSEstimator{
  18. d.hasB,
  19. d.prevPTS,
  20. d.prevDTS,
  21. append([]uint32(nil), d.cache...),
  22. d.interval,
  23. }
  24. }
  25. func (d *DTSEstimator) add(pts uint32) {
  26. i := 0
  27. l := len(d.cache)
  28. if l >= 4 {
  29. l--
  30. // i = l - 3
  31. d.cache = append(d.cache[:0], d.cache[1:]...)[:l]
  32. }
  33. for ; i < l; i = i + 1 {
  34. if d.cache[i] > pts {
  35. break
  36. }
  37. }
  38. d.cache = append(d.cache, pts)
  39. d.cache = append(d.cache[:i+1], d.cache[i:l]...)
  40. d.cache[i] = pts
  41. }
  42. // Feed provides PTS to the estimator, and returns the estimated DTS.
  43. func (d *DTSEstimator) Feed(pts uint32) uint32 {
  44. interval := util.Conditoinal(pts > d.prevPTS, pts-d.prevPTS, d.prevPTS-pts)
  45. if interval > 10*d.interval {
  46. *d = *NewDTSEstimator()
  47. }
  48. d.interval = interval
  49. d.add(pts)
  50. dts := pts
  51. if !d.hasB {
  52. if pts < d.prevPTS {
  53. d.hasB = true
  54. dts = d.cache[0]
  55. }
  56. } else {
  57. dts = d.cache[0]
  58. }
  59. if d.prevDTS > dts {
  60. dts = d.prevDTS
  61. }
  62. // if d.prevDTS >= dts {
  63. // dts = d.prevDTS + 90
  64. // }
  65. d.prevPTS = pts
  66. d.prevDTS = dts
  67. return dts
  68. }