Commit 1d135a80 authored by Jean-Paul Saman's avatar Jean-Paul Saman

RTP reordering fixes.

parent 52932184
...@@ -111,7 +111,6 @@ struct access_sys_t ...@@ -111,7 +111,6 @@ struct access_sys_t
uint32_t i_last_pcr; /* last known good PCR */ uint32_t i_last_pcr; /* last known good PCR */
block_t *p_list; /* list of packets to rearrange */ block_t *p_list; /* list of packets to rearrange */
block_t *p_end; /* last packet in p_list */ block_t *p_end; /* last packet in p_list */
block_t *p_next; /* p_next ?? */
}; };
/***************************************************************************** /*****************************************************************************
...@@ -252,7 +251,6 @@ static int Open( vlc_object_t *p_this ) ...@@ -252,7 +251,6 @@ static int Open( vlc_object_t *p_this )
p_sys->i_rtp_late = var_CreateGetInteger( p_access, "rtp-late" ); p_sys->i_rtp_late = var_CreateGetInteger( p_access, "rtp-late" );
p_sys->p_list = NULL; p_sys->p_list = NULL;
p_sys->p_end = NULL; p_sys->p_end = NULL;
p_sys->p_next = NULL;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -336,7 +334,7 @@ static block_t *BlockUDP( access_t *p_access ) ...@@ -336,7 +334,7 @@ static block_t *BlockUDP( access_t *p_access )
return NULL; return NULL;
} }
if( p_block->i_buffer >= p_sys->i_mtu && p_sys->b_auto_mtu && if( (p_block->i_buffer >= p_sys->i_mtu) && p_sys->b_auto_mtu &&
p_sys->i_mtu < 32767 ) p_sys->i_mtu < 32767 )
{ {
/* Increase by 100% */ /* Increase by 100% */
...@@ -351,9 +349,11 @@ static block_t *BlockUDP( access_t *p_access ) ...@@ -351,9 +349,11 @@ static block_t *BlockUDP( access_t *p_access )
* rtp_ChainInsert - insert a p_block in the chain and * rtp_ChainInsert - insert a p_block in the chain and
* look at the sequence numbers. * look at the sequence numbers.
*/ */
static inline void rtp_ChainInsert( access_t *p_access, block_t **pp_list, block_t **pp_end, block_t *p_block ) static inline void rtp_ChainInsert( access_t *p_access, block_t *p_block )
{ {
block_t *p_tmp = NULL; access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
block_t *p_list = p_sys->p_list;
block_t *p_end = p_sys->p_end;
block_t *p = NULL; block_t *p = NULL;
uint16_t i_new = 0; uint16_t i_new = 0;
uint16_t i_cur = 0; uint16_t i_cur = 0;
...@@ -361,37 +361,37 @@ static inline void rtp_ChainInsert( access_t *p_access, block_t **pp_list, block ...@@ -361,37 +361,37 @@ static inline void rtp_ChainInsert( access_t *p_access, block_t **pp_list, block
uint32_t i_pcr_new = 0; uint32_t i_pcr_new = 0;
if( !p_block ) return; if( !p_block ) return;
if( *pp_list == NULL ) if( !p_list )
{ {
*pp_list = p_block; p_sys->p_list = p_block;
*pp_end = p_block; p_sys->p_end = p_block;
return; return;
} }
/* Appending packets at the end of the chain is the normal case */ /* Appending packets at the end of the chain is the normal case */
i_pcr_new = ( (p_block->p_buffer[4] << 24) + i_pcr_new = ( (p_block->p_buffer[4] << 24) +
(p_block->p_buffer[5] << 16) + (p_block->p_buffer[5] << 16) +
(p_block->p_buffer[6] << 8) + (p_block->p_buffer[6] << 8) +
p_block->p_buffer[7] ); p_block->p_buffer[7] );
i_new = ( (p_block->p_buffer[2] << 8 ) + p_block->p_buffer[3] ); i_new = ( (p_block->p_buffer[2] << 8 ) + p_block->p_buffer[3] );
i_cur = ( (p_end->p_buffer[2] << 8 ) + p_end->p_buffer[3] );
p = *pp_end; i_expected = i_cur + 1;
i_cur = ( (p->p_buffer[2] << 8 ) + p->p_buffer[3] );
i_expected = ((i_cur+1) % RTP_SEQ_NUM_SIZE);
if( (i_new - i_expected) >= 0 ) /* Append at the end? */ if( (i_new - i_expected) >= 0 ) /* Append at the end? */
{ {
msg_Dbg( p_access, ">> append %p(%u)==%p(%u)\n", p_block, i_cur, p, i_new ); msg_Dbg( p_access, "RTP: append %u after %u", i_new, i_cur );
p->p_next = *pp_end = p_block; p_end->p_next = p_block;
p_sys->p_end = p_end->p_next;
return; return;
} }
/* Add to the front fo the chain? */ /* Add to the front fo the chain? */
p = *pp_list; p = p_list;
i_new = ( (p_block->p_buffer[2] << 8 ) + p_block->p_buffer[3] );
i_cur = ( (p->p_buffer[2] << 8 ) + p->p_buffer[3] ); i_cur = ( (p->p_buffer[2] << 8 ) + p->p_buffer[3] );
if( i_cur > i_new ) if( (i_expected - i_new) > 0 )
{ {
msg_Dbg( p_access, ">> prepend %p(%u)==%p(%u)\n", p_block, i_cur, p, i_new ); msg_Dbg( p_access, "RTP: prepend %u before %u", i_cur, i_new );
p_block->p_next = p; p_block->p_next = p;
*pp_list = p_block; p_sys->p_list = p_block;
return; return;
} }
/* The packet can't be added to the front or the end of the chain, /* The packet can't be added to the front or the end of the chain,
...@@ -400,10 +400,9 @@ static inline void rtp_ChainInsert( access_t *p_access, block_t **pp_list, block ...@@ -400,10 +400,9 @@ static inline void rtp_ChainInsert( access_t *p_access, block_t **pp_list, block
while( p ) while( p )
{ {
i_cur = (p->p_buffer[2] << 8 ) + p->p_buffer[3]; i_cur = (p->p_buffer[2] << 8 ) + p->p_buffer[3];
i_expected = (i_cur+1) % RTP_SEQ_NUM_SIZE; i_expected = i_cur+1;
msg_Dbg( p_access, "i_cur: %u, i_new: %u", i_cur, i_new); if( (i_cur - i_new) == 0 )
if( i_cur == i_new )
{ {
uint32_t i_pcr_cur = ( (p->p_buffer[4] << 24) + uint32_t i_pcr_cur = ( (p->p_buffer[4] << 24) +
(p->p_buffer[5] << 16) + (p->p_buffer[5] << 16) +
...@@ -420,10 +419,12 @@ static inline void rtp_ChainInsert( access_t *p_access, block_t **pp_list, block ...@@ -420,10 +419,12 @@ static inline void rtp_ChainInsert( access_t *p_access, block_t **pp_list, block
* else if( i_pcr_cur < i_pcr_new ) */ * else if( i_pcr_cur < i_pcr_new ) */
break; break;
} }
else if( i_expected >= i_new ) /* insert in chain */ else if( (i_expected - i_new) >= 0 ) /* insert in chain */
{ {
block_t *p_tmp = NULL;
p_tmp = p->p_next; p_tmp = p->p_next;
msg_Dbg( p_access, ">> insert between %p(%u)==%p(%u)", p, i_cur, p_tmp, i_new ); msg_Dbg( p_access, "RTP: insert %u after %u", i_new, i_cur );
p->p_next = p_block; p->p_next = p_block;
p_block->p_next = p_tmp; p_block->p_next = p_tmp;
return; return;
...@@ -431,6 +432,8 @@ static inline void rtp_ChainInsert( access_t *p_access, block_t **pp_list, block ...@@ -431,6 +432,8 @@ static inline void rtp_ChainInsert( access_t *p_access, block_t **pp_list, block
if( !p->p_next ) break; if( !p->p_next ) break;
p = p->p_next; p = p->p_next;
} }
msg_Dbg(p_access, "RTP: trashing duplicate %d", i_new );
block_Release( p_block );
} }
/* /*
...@@ -458,10 +461,11 @@ static inline block_t *rtp_ChainSend( access_t *p_access, block_t **pp_list, uin ...@@ -458,10 +461,11 @@ static inline block_t *rtp_ChainSend( access_t *p_access, block_t **pp_list, uin
while( p ) while( p )
{ {
i_cur = ( (p->p_buffer[2] << 8 ) + p->p_buffer[3] ); i_cur = (p->p_buffer[2] << 8 ) + p->p_buffer[3];
msg_Dbg( p_access, "rtp_ChainSend: i_cur %u, i_seq %u", i_cur, i_seq ); if( (i_cur - i_seq) == 0 )
if( i_cur == i_seq )
{ {
msg_Dbg( p_access, "rtp_ChainSend: sequence number %u", i_seq );
i_seq++; /* sent all packets that are received in order */ i_seq++; /* sent all packets that are received in order */
/* Remember PCR and sequence number of packet /* Remember PCR and sequence number of packet
...@@ -489,23 +493,24 @@ static inline block_t *rtp_ChainSend( access_t *p_access, block_t **pp_list, uin ...@@ -489,23 +493,24 @@ static inline block_t *rtp_ChainSend( access_t *p_access, block_t **pp_list, uin
p->i_buffer -= i_skip; p->i_buffer -= i_skip;
p->p_buffer += i_skip; p->p_buffer += i_skip;
} }
else if( i_cur > i_seq ) else if( (i_cur - i_seq) > 0 )
{ {
if( p_prev ) if( p_prev )
{ {
*pp_list = p; p_sys->p_list = p;
p_prev->p_next = NULL; p_prev->p_next = NULL;
p_sys->i_last_pcr = i_pcr_prev; p_sys->i_last_pcr = i_pcr_prev;
p_sys->i_sequence_number = i_seq_prev; p_sys->i_sequence_number = i_seq_prev;
return p_send; return p_send;
} }
/* FiXME: or should we return NULL here? */ goto out;
return NULL;
} }
p_prev = p; p_prev = p;
if (!p->p_next) break; if (!p->p_next) break;
p = p->p_next; p = p->p_next;
} }
out:
/* We have walked through the complete chain and all packets are /* We have walked through the complete chain and all packets are
* in sequence - so send the whole chain * in sequence - so send the whole chain
*/ */
...@@ -520,8 +525,7 @@ static inline block_t *rtp_ChainSend( access_t *p_access, block_t **pp_list, uin ...@@ -520,8 +525,7 @@ static inline block_t *rtp_ChainSend( access_t *p_access, block_t **pp_list, uin
if( i_payload_type == 14 ) i_skip += 4; if( i_payload_type == 14 ) i_skip += 4;
/* Update the list pointers */ /* Update the list pointers */
*pp_list = NULL; p_sys->p_list = NULL;
p_sys->p_next = NULL;
p_sys->p_end = NULL; p_sys->p_end = NULL;
p_sys->i_sequence_number = ( (p->p_buffer[2] << 8 ) + p_sys->i_sequence_number = ( (p->p_buffer[2] << 8 ) +
p->p_buffer[3] ); p->p_buffer[3] );
...@@ -602,10 +606,14 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block ) ...@@ -602,10 +606,14 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block )
*/ */
if( p_sys->b_first_seqno ) if( p_sys->b_first_seqno )
{ {
p_sys->i_sequence_number = i_sequence_number - 1; p_sys->i_sequence_number = i_sequence_number;
p_sys->i_last_pcr = i_pcr; p_sys->i_last_pcr = i_pcr;
p_sys->b_first_seqno = VLC_FALSE; p_sys->b_first_seqno = VLC_FALSE;
i_sequence_expected = i_sequence_number;
} }
else
i_sequence_expected = p_sys->i_sequence_number + 1;
#if 0 #if 0
/* Emulate packet loss */ /* Emulate packet loss */
if ( (i_sequence_number % 4000) == 0) if ( (i_sequence_number % 4000) == 0)
...@@ -615,18 +623,18 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block ) ...@@ -615,18 +623,18 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block )
return NULL; return NULL;
} }
#endif #endif
i_sequence_expected = ((p_sys->i_sequence_number + 1) % RTP_SEQ_NUM_SIZE);
if( i_sequence_expected != i_sequence_number ) if( (i_sequence_expected - i_sequence_number) != 0 )
{ {
/* Handle out of order packets */ /* Handle out of order packets */
if( p_sys->i_rtp_late > 0 ) if( p_sys->i_rtp_late > 0 )
{ {
if( i_sequence_number > i_sequence_expected ) if( (i_sequence_number - i_sequence_expected) > 0 )
{ {
msg_Warn( p_access, msg_Warn( p_access,
"RTP packet out of order (too early) expected %u, current %u", "RTP packet out of order (too early) expected %u, current %u",
i_sequence_expected, i_sequence_number ); i_sequence_expected, i_sequence_number );
if( (i_pcr - p_sys->i_last_pcr) > (p_sys->i_rtp_late*90) ) if( (i_pcr - p_sys->i_last_pcr) >= (p_sys->i_rtp_late*90) )
{ {
block_t *p_start = p_sys->p_list; block_t *p_start = p_sys->p_list;
uint16_t i_start = (!p_start) ? p_sys->i_sequence_number : uint16_t i_start = (!p_start) ? p_sys->i_sequence_number :
...@@ -638,15 +646,15 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block ) ...@@ -638,15 +646,15 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block )
msg_Warn( p_access, msg_Warn( p_access,
"Gap too big resyncing: delta %u, held for %d ms", "Gap too big resyncing: delta %u, held for %d ms",
(i_pcr - p_sys->i_last_pcr), p_sys->i_rtp_late ); (i_pcr - p_sys->i_last_pcr), p_sys->i_rtp_late );
rtp_ChainInsert( p_access, &p_sys->p_list, &p_sys->p_end, p_block ); rtp_ChainInsert( p_access, p_block );
return rtp_ChainSend( p_access, &p_sys->p_list, i_start ); return rtp_ChainSend( p_access, &p_sys->p_list, i_start );
} }
/* hold packets that arrive too early. */ /* hold packets that arrive too early. */
rtp_ChainInsert( p_access, &p_sys->p_list, &p_sys->p_end, p_block ); rtp_ChainInsert( p_access, p_block );
return rtp_ChainSend( p_access, &p_sys->p_list, i_sequence_expected ); return rtp_ChainSend( p_access, &p_sys->p_list, i_sequence_expected );
} }
else if( /* ((i_sequence_expected - i_sequence_number ) > 0) && */ else if( /* ((i_sequence_expected - i_sequence_number ) > 0) && */
(i_pcr <= p_sys->i_last_pcr) ) (p_sys->i_last_pcr - i_pcr) >= 0 )
{ {
msg_Warn( p_access, msg_Warn( p_access,
"RTP packet out of order (duplicate or too late) expected %u, current %u .. trashing it", "RTP packet out of order (duplicate or too late) expected %u, current %u .. trashing it",
...@@ -698,7 +706,7 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block ) ...@@ -698,7 +706,7 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block )
} }
else if( (p_sys->i_rtp_late > 0) && p_sys->p_list ) else if( (p_sys->i_rtp_late > 0) && p_sys->p_list )
{ {
if( i_pcr <= p_sys->i_last_pcr ) if( (p_sys->i_last_pcr - i_pcr) >= 0 )
{ {
msg_Warn( p_access, msg_Warn( p_access,
"RTP packet out of order (duplicate) expected %u, current %u .. trashing it", "RTP packet out of order (duplicate) expected %u, current %u .. trashing it",
...@@ -708,7 +716,7 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block ) ...@@ -708,7 +716,7 @@ static block_t *BlockParseRTP( access_t *p_access, block_t *p_block )
p_sys->i_last_pcr = i_pcr; p_sys->i_last_pcr = i_pcr;
return NULL; return NULL;
} }
rtp_ChainInsert( p_access, &p_sys->p_list, &p_sys->p_end, p_block ); rtp_ChainInsert( p_access, p_block );
return rtp_ChainSend( p_access, &p_sys->p_list, i_sequence_expected ); return rtp_ChainSend( p_access, &p_sys->p_list, i_sequence_expected );
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment