-
Notifications
You must be signed in to change notification settings - Fork 151
Description
One more scenario found where MP4 edit-list support (#1185) breaks smooth playback ( real customer impacted).
Scenario is originated from Ads insertion into streaming playback, but in general such circumstances could appear on any segmented streams that uses adaptive bitrate playback and mixes content without buffers flush.
Let assume stream A (main video) has edit list with start=0:00:00.083416750.
And stream B (short Ad) has edit list with start=0:00:00.041711111
Now we play Stream A for 15 mins, next Stream B for 30 secs and continue Stream A starting from 15th minute
Also player uses timestampOffset to align pieces in timeline.
for stream B: m_timestampOffset={"value":1066.856901}
in for second part stream A: m_timestampOffset={"value":195.9440000990993}
So last frame from Stream B goes with these numbers:
original values from qtdemux in AppSinkFlushCapsWorkaroundProbe::probe(): buffer: 0x233f540, pts 0:00:29.988355555, dts 0:00:29.946644444, dur 0:00:00.041711111, size 999, offset none, offset_end none, flags 0x6000
original sample on entry in SourceBufferPrivate::didReceiveSample() (adjusted by segment start=0:00:00.041711111):
{"size":999,"pts":{"value":29.946644444,"numerator":29946644444,"denominator":1000000000,"flags":1},"dts":{"value":29.904933333,"numerator":29904933333,"denominator":1000000000,"flags":1},
and updated sample adjusted by m_timestampOffset={"value":1066.856901} :
{"size":999,"pts":{"value":1096.803545444,"numerator":1096803545444,"denominator":1000000000,"flags":1},"dts":{"value":1096.761834333,"numerator":1096761834333,"denominator":1000000000,"flags":1},
The first sample from stream A at 15min looks like:
original values from qtdemux in AppSinkFlushCapsWorkaroundProbe::probe(): buffer: 0x1fe7540, pts 0:15:00.984317650, dts 0:15:00.900900900, dur 0:00:00.041708375, size 1282, offset none, offset_end none, flags 0x4040)
original sample on entry in SourceBufferPrivate::didReceiveSample() (adjusted by segment start=0:00:00.083416750):
{"size":1282,"pts":{"value":900.9009009,"numerator":900900900900,"denominator":1000000000,"flags":1},"dts":{"value":900.81748415,"numerator":900817484150,"denominator":1000000000,"flags":1},
and updated sample adjusted by m_timestampOffset={"value":195.9440000990993}
{"size":1282,"pts":{"value":1096.844900999,"numerator":1096844900999,"denominator":1000000000,"flags":1},"dts":{"value":1096.761484249,"numerator":1096761484249,"denominator":1000000000,"flags":1}
Next two bad things happen in didReceiveSample():
-
removing last frame from stream B (in fact it is already passed downstream and will be decoded/displayed):
SourceBufferPrivateGStreamer::didReceiveSample(5D620002) Discovered out-of-order frames, from: {"size":999,"pts":{"value":1096.803545444,"numerator":1096803545444,"denominator":1000000000,"flags":1},"dts":{"value":1096.761834333,"numerator":1096761834333,"denominator":1000000000,"flags":1},
Jul 15 13:42:54.969223 E0B7B1-APPSTB-301000193203 WPEWebProcess[28120]: 250715-12:42:54.969114 [mod=Media, lvl=DEBUG] [tid=18] TrackBuffer::didReceiveSample(5D621B75) removing sample {"size":999,"pts":{"value":1096.803545444,"numerator":1096803545444,"denominator":1000000000,"flags":1},"dts":{"value":1096.761834333,"numerator":1096761834333,"denominator":1000000000,"flags":1}, -
not inserting first frame from stream A (really, really bad if this is an I-Frame), extra debug shows this:
SourceBufferPrivateGStreamer::didReceiveSample(5D620002) skip unordered sample, lastEnqueuedDecodeKey: dts:{"value":1096.761834333,"numerator":1096761834333,"denominator":1000000000,"flags":1} pts:{"value":1096.803545444,"numerator":1096803545444,"denominator":1000000000,"flags":1}
When I have removed edit list support, all PTSes/DTSes are aligned and no frame is lost:
Stream B has last inserted frame: pts: 1096,845256555, dts: 1096,80354544
Stream A has first inserted frame: pts: 1096,928317749 dts: 1096,844900999
It is also not a perfect state, since last frame from stream B will have extended presentation duration, but this is rather pure player issue.
Some ideas went trough my mind while analyzing this situation (all have drawbacks, unfortunately):
- adjust timestampOffset with offsets from edit-list
- adjust/keep in sync lastEnqueuedDecodeKey when we have removed samples from buffer
- keep/remove all frames staring from "random-access points" to avoid macroblocks/artefacts when decoding
I can provide more logs/details related to my case if needed.
Any proposal to try besides reverting edit-list support is much appreciated.
Thank you.
Vova.