The problem is actually in the last condition check as
Anderson pointed out:
(frontPacket->GetReliableSeqNo() !=
(UINT16)(m_uReliableSeqNo +
frontPacket->IsReliable())
Disabling the ulMinimumToBuffer check won't solve the
problem because the
last condition shown above is TRUE and it's OR-ed with the
rest of checks,
so we would still return HXR_BUFFERING.
ulMinimumToBuffer is the depth of transport buffer, it's the
cushion
necessary to handle the resend of loss packet. We try to
give enough
time(ulMinimumToBuffer) to recover these loss package, but
we give up if we
have waited longer than ulMinimumToBuffer EXCEPT if the lost
packet is a
reliable packet.
The ulMinimumToBuffer check doesn't solely depend on the
next packet
received which can be a problem for sparse stream as Eric
points out, it
also measures how long the loss packet has been in the
queue(TimeInBuffer <
Timeval((float)ulMinimumToBuffer / 1000.0)), thus the
ulMinimumToBuffer
checks are OK even for the sparse streams.
It seems the packets for Event stream are all marked
reliabled. Reliable
packet means the client will keep trying to recover it from
the server even
it means to halt the playback of that stream.
In this case, because it's live, the server/producer likely
won't resend any
of those lost packets. Thus we halt the event stream.
I suggest to add m_bIsLive check and only enforce the
reliable packet check
if the stream is not live.
-->Henry
> -----Original Message-----
> From: player-dev-bounces helixcommunity.org
> [mailto:player-dev-bounces helixcommunity.org] On
Behalf Of Eric Hyche
> Sent: Wednesday, September 27, 2006 9:15 AM Ping
> To: 'Anderson Luiz Brunozi'; client-dev helixcommunity.org;
> player-dev helixcommunity.org
> Subject: [Player-dev] RE: [Client-dev] Fixing bug 5332.
> Question aboutclient code.
>
>
> Anderson,
>
> I think you have accurately diagnosed the problem. This
code
> clearly was not expecting a sparse stream like an event
> stream. I believe the ulMinimumToBuffer variable is the
> problem - it is set to something reasonable for a/v
streams,
> but not for event streams. This code expects that
another
> packet will arrive within ulMinimumToBuffer
milliseconds and
> for your case ulMinimumToBuffer is set to 2s, which is
way
> too low for an event stream.
>
> I think that the proper fix would be to simply disable
the
> time enforcement part of the if clause:
>
> ulTimeInQueue < ulMinimumToBuffer
&&
> TimeInBuffer <
Timeval((float)ulMinimumToBuffer / 1000.0)
>
> if this is an event stream. I don't think that for
event
> streams we could just crank the ulMinimumToBuffer
higher,
> since you really don't have an idea how long it might
be
> before another event packet comes along.
>
> We already have a variable m_bSparseStream. However, it
looks
> like that is only set when SetMulticast() is called.
> So we would need to make sure that m_bSparseStream gets
set
> all the time, and then use it to disable the time
enforcement
> above if m_bSpareStream is TRUE.
>
> That's my initial thoughts after looking at it. Others
may
> have other ideas for fixes.
>
> Eric
>
> =============================================
> Eric Hyche (ehyche real.com)
> Technical Lead
> RealNetworks, Inc.
>
> > -----Original Message-----
> > From: client-dev-bounces helixcommunity.org
> > [mailto:client-dev-bounces helixcommunity.org] On
Behalf Of
> Anderson
> > Luiz Brunozi
> > Sent: Wednesday, September 27, 2006 9:09 AM
> > To: client-dev helixcommunity.org;
player-dev helixcommunity.org
> > Subject: [Client-dev] Fixing bug 5332. Question
about client code.
> >
> > Hello, Helix folks,
> >
> > Some time ago I've found a bug in Real Player that
causes
> the player
> > to stop processing RMEvents after an event packet
is lost,
> as reported
> > in BUG 5332:
> >
https://bugs.helixcommunity.org/show_bug.cgi?id=5332
> >
> > I've downloaded the player code, and started
investigating
> it, trying
> > to find why that problem is happening with the
event
> packets, because
> > this feature is very important for us.
> > However, as I still have very little experience
with the
> player code,
> > I'd be glad if I could get some advice from you
who are more
> > experienced, about the code.
> >
> > Below is what I think I've found about the problem
until now, as
> > detailed as I can (sorry if it gets too large),
and after,
> I have some
> > questions about it.
> >
> > For me, it looks like the problem is in the file
> > protocol/transport/common/system/transbuf.cpp.
> > By inserting a lot of printf()'s into that file,
at first into the
> > Insert() function, I've found that after an event
packet is
> lost new
> > incoming event packets continue to be inserted to
m_pPacketDeque,
> > however no packets get out of the queue. Once the
queue
> have its front
> > packet being a "sanitize packet" for
which there was no resend, it
> > just grows indefinetelly.
> >
> > After I could see no problem with the Insert()
function,
> I've turned
> > to investigate the point where the packets should
be
> removed from the
> > pPacketDeque. So, the printf()'s go to the
> > GetPacketFromQueue() function.
> >
> > >From there, I could notice that a lost event
packet is the
> > front packet in the queue, the
GetPacketFromQueue() function always
> > return HXR_BUFFERING. And, finally, here is the
part of the
> code where
> > I think the problem is:
> >
> >
> > // We only want to get packets as soon as
possible for
> FastStart
> > when
> > // before starting playback. If already
playing getting lost
> > packets
> > // faster then usual prevents resent packets
from being
> processed.
> > if ((!m_bFastStart || bPlaying)
&&
> > (!m_bIsEnded
&&
> > m_pPacketDeque->size() <
MAX_QUEUED_PACKETS &&
> > frontPacket->IsLostPacket()
&&
> > ulTimeInQueue < ulMinimumToBuffer
&&
> > TimeInBuffer <
Timeval((float)ulMinimumToBuffer /
> 1000.0)) ||
> > (frontPacket->GetReliableSeqNo() !=
> > (UINT16)(m_uReliableSeqNo +
frontPacket->IsReliable())))
> > {
> > pPacket = 0;
> >
> > m_status = TRANSBUF_FILLING;
> > return HXR_BUFFERING;
> > }
> >
> > This is the condition for returning HXR_BUFFERING.
> > Inside that if() clause, I've inserted a lot of
printf()'s
> for all the
> > variables involved the if() condition:
> >
> > This is what I get after the first lost event
packet (first time
> > HXR_BUFFERING was returned). In this case, the
packet
> > 299 is the lost packet:
> >
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
HXR_BUFFERING
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
m_bFastStart: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
bPlaying: 1
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
m_bIsEnded: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > m_pPacketDeque->size(): 2
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > MAX_QUEUED_PACKETS: 500
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->IsLostPacket(): 1
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
ulTimeInQueue: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > ulMinimumToBuffer: 2000
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
TimeInBuffer: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
Timeval(...): 2
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->GetReliableSeqNo(): 301
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->IsReliable(): 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > m_uReliableSeqNo: 299
> >
> > Here, it looks ok: All conditions on if() clause
are true. At this
> > time, the queue contains two packets: a
placeholder packet for the
> > packet 299, and packet 300.
> >
> > After the packet 301 has arrived, this is what is
printed:
> >
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
HXR_BUFFERING
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
m_bFastStart: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
bPlaying: 1
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
m_bIsEnded: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > m_pPacketDeque->size(): 3
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > MAX_QUEUED_PACKETS: 500
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->IsLostPacket(): 1
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> ulTimeInQueue: 657
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > ulMinimumToBuffer: 2000
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
TimeInBuffer: 2
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
Timeval(...): 2
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->GetReliableSeqNo(): 301
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->IsReliable(): 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > m_uReliableSeqNo: 299
> >
> > >From the above, the following condition on the
if() clause
> > for deciding whether to return HXR_BUFFERING are
not true anymore:
> >
> > TimeInBuffer <
Timeval((float)ulMinimumToBuffer / 1000.0))
> >
> >
> > And after the packet 302 arrives, I get the
following:
> >
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
HXR_BUFFERING
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
m_bFastStart: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
bPlaying: 1
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
m_bIsEnded: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > m_pPacketDeque->size(): 4
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > MAX_QUEUED_PACKETS: 500
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->IsLostPacket(): 1
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> ulTimeInQueue: 3697
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > ulMinimumToBuffer: 2000
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
TimeInBuffer: 4
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
Timeval(...): 2
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->GetReliableSeqNo(): 301
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->IsReliable(): 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > m_uReliableSeqNo: 299
> >
> > Here we already have two of the conditions on that
if()
> clause being
> > false:
> >
> > ulTimeInQueue < ulMinimumToBuffer
&&
> > TimeInBuffer <
Timeval((float)ulMinimumToBuffer / 1000.0))
> >
> > About 20 minutes later (I think so, but not sure
about how
> much time,
> > exactly), when I stop the player, the last event
packet
> received was
> > the packet 695. And this is the last set of prints
I've got:
> >
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
HXR_BUFFERING
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
m_bFastStart: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
bPlaying: 1
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
m_bIsEnded: 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > m_pPacketDeque->size(): 397
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > MAX_QUEUED_PACKETS: 500
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->IsLostPacket(): 1
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > ulTimeInQueue: 745021
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > ulMinimumToBuffer: 2000
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
TimeInBuffer: 746
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
Timeval(...): 2
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->GetReliableSeqNo(): 301
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > frontPacket->IsReliable(): 0
> > DEBUG: RTSPTransportBuffer::GetPacketFromQueue():
> > m_uReliableSeqNo: 299
> >
> > Here, clearly, there is no hope for packet 299 to
arrive,
> however, the
> > queue now has 396 packets with the placeholder for
packet 299 being
> > the front packet.
> >
> >
> > Now, here are my questions about the code:
> >
> > Is there any special reason for the last OR ( || )
operator in if()
> > clause?
> > [As in || (frontPacket->GetReliableSeqNo() !=
> > (UINT16)(m_uReliableSeqNo +
frontPacket->IsReliable()))]
> >
> > If I change that OR into an AND operator, would
there be any "side
> > effects"? Or would there be any other problem
that could arise?
> > (That's mainly what I'm concerned about, as this
code is
> used also for
> > the audio and video streams, right?)
> >
> >
> > I've tried it here, and let the player running for
more than two
> > hours: I could not notice any slide freezing.
Here, "slides" refers
> > the URLs being sent through the event stream.
> > And after stopping the player, from the debug info
I've printed, I
> > could that that, indeed, the player have missed
some
> packets, and got
> > into the if() for returning HXR_BUFFERING a lot of
times,
> but it could
> > get out of it a few seconds later, everytime.
> >
> > For a comparison, in previous tests here, when
running the
> stream over
> > the internet, we usually get at least one event
packet lost
> within 10
> > minutes. (But, on the hand, when running on the
local
> network it may
> > go for hours, or even days without a single packet
loss)
> >
> > May I consider that a fix?
> >
> >
> > Thanks for your patience reading all that, and
sorry if my
> english is
> > not that good,
> >
> >
> > Anderson Luiz Brunozi
> >
> >
> >
> > _______________________________________________
> > Client-dev mailing list
> > Client-dev helixcommunity.org
> > http://lists.helixcommunity.org/mailman/listinfo/clie
nt-dev
> >
>
>
> _______________________________________________
> Player-dev mailing list
> Player-dev helixcommunity.org
> http://lists.helixcommunity.org/mailman/listinfo/play
er-dev
_______________________________________________
Player-dev mailing list
Player-dev helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/play
er-dev
|