mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-07 09:30:56 +08:00
68 lines
1.4 KiB
Go
68 lines
1.4 KiB
Go
package common
|
|
|
|
// DTSEstimator is a DTS estimator.
|
|
type DTSEstimator struct {
|
|
prevDTS uint32
|
|
prevPTS uint32
|
|
prevPrevPTS uint32
|
|
dts func(uint32) uint32
|
|
delta uint32
|
|
}
|
|
|
|
func (d *DTSEstimator) _dts(pts uint32) uint32 {
|
|
// P or I frame
|
|
if pts > d.prevPTS {
|
|
// previous frame was B
|
|
// use the DTS of the previous frame
|
|
if d.prevPTS < d.prevPrevPTS {
|
|
return d.prevPTS
|
|
}
|
|
|
|
// previous frame was P or I
|
|
// use two frames ago plus a small quantity
|
|
// to avoid non-monotonous DTS with B-frames
|
|
return d.prevPrevPTS + 1
|
|
}
|
|
|
|
// B Frame
|
|
// increase by a small quantity
|
|
return d.prevDTS + 1
|
|
}
|
|
func (d *DTSEstimator) _dts2(pts uint32) uint32 {
|
|
return d.prevDTS + d.delta
|
|
}
|
|
|
|
// NewDTSEstimator allocates a DTSEstimator.
|
|
func NewDTSEstimator() *DTSEstimator {
|
|
result := &DTSEstimator{}
|
|
result.dts = func(pts uint32) uint32 {
|
|
if result.prevPTS > 0 {
|
|
result.delta = pts - result.prevPTS
|
|
result.dts = result._dts2
|
|
}
|
|
return pts
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Feed provides PTS to the estimator, and returns the estimated DTS.
|
|
func (d *DTSEstimator) Feed(pts uint32) uint32 {
|
|
dts := d.dts(pts)
|
|
|
|
d.prevPrevPTS = d.prevPTS
|
|
d.prevPTS = pts
|
|
d.prevDTS = dts
|
|
if d.prevPTS > d.prevPrevPTS {
|
|
delta := d.prevPTS - d.prevPrevPTS
|
|
if delta < d.delta {
|
|
d.delta = delta
|
|
}
|
|
} else {
|
|
delta := d.prevPrevPTS - d.prevPTS
|
|
if delta < d.delta {
|
|
d.delta = delta
|
|
}
|
|
}
|
|
return dts
|
|
}
|