asfpacket: Fix pull-mode timestamping handling.

The problem that happens is the following:
* A packet with multiple payloads comes in
* Those payloads get handled one by one
* The first payload contains the first audio payload with timestamp A
* The second payload contains the first video (key)frame with timestamp V (where V < A)

With the previous code, the following would happen:
* the first payload gets processed, then passed to queue_for_stream
* queue_for_stream detects it's the first valid timestamp received and stores
  first_ts = A
* the second payload gets processed, then pass to queue_for_stream
* queue_for_stream detects the timestamp is lower than first_ts... and
  discards it... resulting in losing the first keyframe of the video stream

We've been having this issue for *ages*... it's just that nobody noticed it
that much with playbin. But with playbin2's aggresive multiqueue handling, this
will result in multiqueue not being able to preroll (because the video decoder will
be dropping a ton of buffers before (maybe) receiving the next keyframe).

Tested with over 200 asf files, and they all play the first frame correctly now,
even the most braindead ones.
This commit is contained in:
Edward Hervey 2009-04-23 09:04:41 +02:00
parent e7450c2df7
commit 804f65e6db

View file

@ -121,6 +121,8 @@ static void
gst_asf_payload_queue_for_stream (GstASFDemux * demux, AsfPayload * payload, gst_asf_payload_queue_for_stream (GstASFDemux * demux, AsfPayload * payload,
AsfStream * stream) AsfStream * stream)
{ {
GST_DEBUG_OBJECT (demux, "Got payload for stream %d ts:%" GST_TIME_FORMAT,
stream->id, GST_TIME_ARGS (payload->ts));
/* remember the first timestamp in the stream */ /* remember the first timestamp in the stream */
if (!GST_CLOCK_TIME_IS_VALID (demux->first_ts) && if (!GST_CLOCK_TIME_IS_VALID (demux->first_ts) &&
GST_CLOCK_TIME_IS_VALID (payload->ts)) { GST_CLOCK_TIME_IS_VALID (payload->ts)) {
@ -134,19 +136,13 @@ gst_asf_payload_queue_for_stream (GstASFDemux * demux, AsfPayload * payload,
} }
} }
/* better drop a few frames at the beginning than send bogus timestamps */
if (G_UNLIKELY (payload->ts < demux->first_ts)) {
GST_LOG_OBJECT (stream->pad, "Dropping payload with timestamp %"
GST_TIME_FORMAT " which is before the first timestamp %"
GST_TIME_FORMAT, GST_TIME_ARGS (payload->ts),
GST_TIME_ARGS (demux->first_ts));
gst_buffer_replace (&payload->buf, NULL);
return;
}
/* make timestamps start from 0 */ /* make timestamps start from 0 */
if (!demux->streaming) if (!demux->streaming) {
if (demux->first_ts < payload->ts)
payload->ts -= demux->first_ts; payload->ts -= demux->first_ts;
else
payload->ts = 0;
}
/* remove any incomplete payloads that will never be completed */ /* remove any incomplete payloads that will never be completed */
while (stream->payloads->len > 0) { while (stream->payloads->len > 0) {