GNOME Bugzilla – Bug 787085
tsdemux: Sudden jump in PTS when there is a backward jump in PCR
Last modified: 2018-11-03 14:12:50 UTC
With UDP input, whenever there is a backward jump in PCR, PTS calculation is going wrong. In TS demuxer PTS is calculated using below equation out_PTS = PTS + pcr_offset + base_time - base_pcrtime; whenever there is a backward jump in PCR is pcr_offset is updated with the deviation between base_pcrtime and current pcr time. And the same offset is added with PTS also. This sudden jump in PTS is chocking the pipeline. Pipelines and buffer time stamps ------------------------------- gst-launch-1.0 udpsrc port=8000 ! tsdemux ! checksumsink 0:00:30.598786471 680c47336866cc84763d57f70f6da3fac8883fd9 0:00:30.678786471 494de7e78e362b8094a79e8845ef06248d83098f 9:23:15.335157152 4db283bf6f1afb771ab17bfd390bccd76e848f4b -- sudden jump 0:00:30.796141979 c37fa545074d1a06f58e94fe817f041f81e036ab 0:00:30.756141835 7519205aeaa27e312616bcd86c9f6f143a61b650 0:00:30.836141835 4d78efa7f0080a8cbb38aac2ca005f15e8d648ec gst-launch-1.0 udpsrc port=8000 ! tsdemux ! h264parse ! avdec_h264 ! checksumsink --gst-debug=3 0:00:10.138379707 6976 0x810400 WARN videodecoder gstvideodecoder.c:2775:gst_video_decoder_prepare_finish_frame:<avdec_h264-0> decreasing timestamp (0:00:10.692303114 < 9:22:52.969321645) 9:22:52.969321645 2eabf26677ebc0f85852b860d07f8ef4d1a93b17 0:00:10.189489982 6976 0x810400 WARN videodecoder gstvideodecoder.c:2775:gst_video_decoder_prepare_finish_frame:<avdec_h264-0> decreasing timestamp (0:00:10.732303113 < 9:22:52.969321645) 9:22:52.969321645 1e076ae62acb9aaa69c5a149138e2c9968ca9545 0:00:10.235837073 6976 0x810400 WARN videodecoder gstvideodecoder.c:2775:gst_video_decoder_prepare_finish_frame:<avdec_h264-0> decreasing timestamp (0:00:10.812303113 < 9:22:52.969321645) 9:22:52.969321645 ab92e908e19b1ac48697fa73baa695a587a39e24 0:00:10.287201163 6976 0x810400 WARN videodecoder gstvideodecoder.c:2775:gst_video_decoder_prepare_finish_frame:<avdec_h264-0> decreasing timestamp (0:00:10.852303113 < 9:22:52.969321645)
Would be great if you could make available / attach a sample stream with which to reproduce this.
Also, is it really a backward jump or a side effect of tsdemux not handling packet reordering ?
It is because of backward jump. This issue happens when the following sequence occurs Backward jump -> PES header parse with PTS -> forward jump After the forward jump there is no issue in PTS calculation. The following sequence doesn't have any issue, because during forward jump base_pcrtime is updated with pcr_offset. Backward jump -> forward jump -> PES header parse with PTS In the following link sharing the captured udp input. https://drive.google.com/file/d/0B88Uu4_Va04Fazk2dkxWQkFQVFk/view?usp=sharing https://drive.google.com/file/d/0B88Uu4_Va04FMmhfZk5oME1YelE/view?usp=sharing
If we update base_pcrtime and base_time for backward PCR jump we can overcome this issue. But there are chances that both base_pcrtime and pcroffset may become negative. Right now I am not sure about the side effects of base_pcrtime having negative value.
Is there any other update on this issue?
Did anybody reproduce this issue?
What's the source of this stream ? UDP ? DVB ? Something else ? fwiw, vlc chokes even faster on it. Not a good sign.
It is captured and streamed(UDP) from IRD, during bad weather condition.
It is a DVB stream.
can we add some error resilience, whenever there is a backward jump in PCR followed by PES parsing with PTS?
It can't be a DVB *and* a UDP stream. It's either: * DVB (i.e. over satelitte/cable/terrestrial), in which case you can only have packet losses and not reordering (order is handled at DVB transmission level) * UDP, in which case you can have both packet loss *and* reordering mpeg-ts is *not* designed for coping with reordering. You need another solution. Such solutions could be: * You have a dedicated network with guarantees of no packet reordering/loss * RTP (encapsulating mpeg-ts within that), which can detect/handle reordering * not using UDP
Thanks Edward for your suggestions. One more observation on this issue: UDP input buffer has 7 TS packers and two of them are having PCRs. one PCR is going backward and the next one is having proper value. Consider PTS=12:00:00, base_pcr = 12:00:00 and offset=00:00:00 current_pcr=10:00:00. For explanation purpose consider skew=0 and base_time=0. When the backward jump happens (by 02:00:00) In calculate_skew() function following changes will happen offset = 02:00:00 base_pcr = 12:00:00 last_pcr = 12:00:00 -> current_pcr + offset In function mpegts_packetizer_pts_to_ts() out_PTS = in_PTS + offset = 12:00:00 + 02:00:00 = 14:00:00 if (G_UNLIKELY (pcr_pid != 0x1fff && ABSDIFF (res, pcrtable->last_pcrtime) > 15 * GST_SECOND)) res = GST_CLOCK_TIME_NONE; else { GstClockTime tmp = pcrtable->base_time + pcrtable->skew; if (tmp + res > pcrtable->base_pcrtime) res += tmp - pcrtable->base_pcrtime; else res = GST_CLOCK_TIME_NONE; According to above code first if condition will be satisfied and GST_CLOCK_TIME_NONE will be returned. Here there is *no issue*. Now we have a proper PCR (current_pcr=12:00:00). As per calculate_skew function, first add offset with current_pcr current_pcr = 12:00:00 + 02:00:00 = 14:00:00 Then this value is assigned to last_pcr. last_pcr = 14:00:00 offset = 02:00:00 Since both PCR buffers are present in same UDP buffer, both are having same time stamps. So the following condition will be satisfied and base_pcr time will not be updated in calculate_skew(). So now we have base_pcr=12:00:00 /* Ignore packets received at 100% the same time (i.e. from the same input buffer) */ if (G_UNLIKELY (time == pcr->prev_in_time && GST_CLOCK_TIME_IS_VALID (pcr->prev_in_time))) goto no_skew; Now in function mpegts_packetizer_pts_to_ts() out_PTS = in_PTS + offset = 12:00:00 + 02:00:00 = 14:00:00 As per above code snippet of mpegts_packetizer_pts_to_ts(), the if condition will fail because out_PTS == last_pcr and in else part following code will be executed. if (tmp + res > pcrtable->base_pcrtime) res += tmp - pcrtable->base_pcrtime; So the out_PTS = out_PTS - base_pcr = 14:00:00 - 12:00:00 = 02:00:00. This is the *issue*. If we are completely ignoring the second PCR buffer in calculate_skew() as mentioned in comments there won't be any issue. But we updating last_pcr, that leads to this issue.
Thanks, that makes more sense. Will have a look at it later. Can you attach a pcap capture so I can reproduce it with proper timestamps ?
pcap file is shared here. https://drive.google.com/file/d/0B88Uu4_Va04FZWRsWTF2eWlPQTg/view?usp=sharing
Is there any update on this issue?
can we avoid updating following variables, whenever two pcr buffers are having same time stamps? pcr->last_pcrtime pcr->base_pcrtime pcr->pcroffset With this change we can overcome from this issue. Please let me know your comments on this change.
-- GitLab Migration Automatic Message -- This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/604.