[vlc-commits] demux: asf: use send time as base time for pcr (fix #6662, #8795)
Francois Cartegnie
git at videolan.org
Sat Dec 7 19:11:57 CET 2013
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Sat Nov 9 20:43:48 2013 +0900| [8e7a55dd83d08f0ff637188d0ae7c4562a90a592] | committer: Francois Cartegnie
demux: asf: use send time as base time for pcr (fix #6662, #8795)
Using lowest PTS or DTS is a bad idea, as lower video packets are sent
ahead of pts, and most audio tracks are sending packets near to pts.
So we had audio packets coming late, with a lower pts, and corrupted
our PCR as we take the lowest pts among tracks.
We can't also guess the full tracks rolls, so updating after a full
roll instead of each packet is useless.
Send time is a reliable base time.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8e7a55dd83d08f0ff637188d0ae7c4562a90a592
---
modules/demux/asf/asf.c | 55 ++++++++++++++++++++++++++++++++---------------
1 file changed, 38 insertions(+), 17 deletions(-)
diff --git a/modules/demux/asf/asf.c b/modules/demux/asf/asf.c
index 1037592..3ce8a76 100644
--- a/modules/demux/asf/asf.c
+++ b/modules/demux/asf/asf.c
@@ -83,7 +83,6 @@ typedef struct
mtime_t i_time;
block_t *p_frame; /* use to gather complete frame */
-
} asf_track_t;
struct demux_sys_t
@@ -213,6 +212,9 @@ static int Demux( demux_t *p_demux )
p_sys->i_time = GetMoviePTS( p_sys );
if( p_sys->i_time >= 0 )
{
+#ifdef ASF_DEBUG
+ msg_Dbg( p_demux, "Setting PCR to %"PRId64, p_sys->i_time );
+#endif
es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time+1 );
}
@@ -514,19 +516,17 @@ static void SendPacket(demux_t *p_demux, asf_track_t *tk)
block_t *p_gather = block_ChainGather( tk->p_frame );
- if( p_gather->i_pts > VLC_TS_INVALID )
- tk->i_time = p_gather->i_pts - VLC_TS_0;
-
- if( p_sys->i_time < 0 )
+ if( p_sys->i_time < VLC_TS_0 && tk->i_time > VLC_TS_INVALID )
{
- es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_gather->i_pts );
+ p_sys->i_time = tk->i_time;
+ es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time );
#ifdef ASF_DEBUG
- msg_Dbg( p_demux, "setting PCR to %"PRId64, p_gather->i_pts );
+ msg_Dbg( p_demux, " setting PCR to %"PRId64, p_sys->i_time );
#endif
}
#ifdef ASF_DEBUG
- msg_Dbg( p_demux, "sending packet dts %"PRId64" %"PRId64, p_gather->i_dts, p_gather->i_pts );
+ msg_Dbg( p_demux, " sending packet dts %"PRId64" pts %"PRId64" pcr %"PRId64, p_gather->i_dts, p_gather->i_pts, p_sys->i_time );
#endif
es_out_Send( p_demux->out, tk->p_es, p_gather );
@@ -664,9 +664,13 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
mtime_t i_base_pts;
uint8_t i_pts_delta = 0;
+ uint32_t i_payload_data_length = 0;
+ uint32_t i_temp_payload_length = 0;
+
/* Non compressed */
- if( i_replicated_data_length > 1 ) // should be at least 8 bytes
+ if( i_replicated_data_length > 7 ) // should be at least 8 bytes
{
+ /* Followed by 2 optional DWORDS, offset in media and presentation time */
i_base_pts = (mtime_t)GetDWLE( pkt->p_peek + pkt->i_skip + 4 );
/* Parsing extensions, See 7.3.1 */
@@ -679,7 +683,12 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
if( ! pkt->left || pkt->i_skip >= pkt->left )
return -1;
}
- /* Compressed sub payload */
+ else if ( i_replicated_data_length == 0 )
+ {
+ /* optional DWORDS missing */
+ i_base_pts = (mtime_t)pkt->send_time;
+ }
+ /* Compressed payload */
else if( i_replicated_data_length == 1 )
{
/* i_media_object_offset is presentation time */
@@ -692,24 +701,22 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
}
else
{
- i_base_pts = (mtime_t)pkt->send_time;
+ /* >1 && <8 Invalid replicated length ! */
+ msg_Warn( p_demux, "Invalid replicated data length detected." );
+ i_payload_data_length = pkt->length - pkt->padding_length - pkt->i_skip;
+ goto skip;
}
if (i_base_pts < 0) i_base_pts = 0; // FIXME?
i_base_pts *= 1000;
- uint32_t i_payload_data_length = 0;
- uint32_t i_temp_payload_length = 0;
if( pkt->multiple ) {
if (GetValue2b(&i_temp_payload_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->length_type) < 0)
return -1;
} else
i_temp_payload_length = pkt->length - pkt->padding_length - pkt->i_skip;
- if( ! i_temp_payload_length || i_temp_payload_length > pkt->left )
- return -1;
- else
- i_payload_data_length = i_temp_payload_length;
+ i_payload_data_length = i_temp_payload_length;
#ifdef ASF_DEBUG
msg_Dbg( p_demux,
@@ -720,6 +727,12 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
" pts=%"PRId64" st=%"PRIu32, i_base_pts, pkt->send_time );
#endif
+ if( ! i_payload_data_length || i_payload_data_length > pkt->left )
+ {
+ msg_Dbg( p_demux, " payload length problem %d %"PRIu32" %"PRIu32, pkt->multiple, i_payload_data_length, pkt->left );
+ return -1;
+ }
+
asf_track_t *tk = p_sys->track[i_stream_number];
if( tk == NULL )
{
@@ -746,6 +759,10 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
if( !tk->p_es )
goto skip;
+ tk->i_time = INT64_C(1000) * pkt->send_time;
+ tk->i_time -= p_sys->p_fp->i_preroll * 1000;
+ tk->i_time -= tk->p_sp->i_time_offset * 10;
+
uint32_t i_subpayload_count = 0;
while (i_payload_data_length)
{
@@ -896,7 +913,10 @@ static int DemuxPacket( demux_t *p_demux )
for( int i_payload = 0; i_payload < i_payload_count ; i_payload++ )
if (DemuxPayload(p_demux, &pkt, i_payload) < 0)
+ {
+ msg_Warn( p_demux, "payload err %d / %d", i_payload + 1, i_payload_count );
return 0;
+ }
if( pkt.left > 0 )
{
@@ -1320,6 +1340,7 @@ static int DemuxInit( demux_t *p_demux )
msg_Dbg( p_demux, "ignoring unknown stream(ID:%d)",
p_sp->i_stream_number );
}
+
es_format_Clean( &fmt );
}
More information about the vlc-commits
mailing list