Commit 8e7a55dd authored by Francois Cartegnie's avatar 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.
parent 882f2d61
...@@ -83,7 +83,6 @@ typedef struct ...@@ -83,7 +83,6 @@ typedef struct
mtime_t i_time; mtime_t i_time;
block_t *p_frame; /* use to gather complete frame */ block_t *p_frame; /* use to gather complete frame */
} asf_track_t; } asf_track_t;
struct demux_sys_t struct demux_sys_t
...@@ -213,6 +212,9 @@ static int Demux( demux_t *p_demux ) ...@@ -213,6 +212,9 @@ static int Demux( demux_t *p_demux )
p_sys->i_time = GetMoviePTS( p_sys ); p_sys->i_time = GetMoviePTS( p_sys );
if( p_sys->i_time >= 0 ) 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 ); 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) ...@@ -514,19 +516,17 @@ static void SendPacket(demux_t *p_demux, asf_track_t *tk)
block_t *p_gather = block_ChainGather( tk->p_frame ); block_t *p_gather = block_ChainGather( tk->p_frame );
if( p_gather->i_pts > VLC_TS_INVALID ) if( p_sys->i_time < VLC_TS_0 && tk->i_time > VLC_TS_INVALID )
tk->i_time = p_gather->i_pts - VLC_TS_0;
if( p_sys->i_time < 0 )
{ {
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 #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 #endif
} }
#ifdef ASF_DEBUG #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 #endif
es_out_Send( p_demux->out, tk->p_es, p_gather ); 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 ...@@ -664,9 +664,13 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
mtime_t i_base_pts; mtime_t i_base_pts;
uint8_t i_pts_delta = 0; uint8_t i_pts_delta = 0;
uint32_t i_payload_data_length = 0;
uint32_t i_temp_payload_length = 0;
/* Non compressed */ /* 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 ); i_base_pts = (mtime_t)GetDWLE( pkt->p_peek + pkt->i_skip + 4 );
/* Parsing extensions, See 7.3.1 */ /* 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 ...@@ -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 ) if( ! pkt->left || pkt->i_skip >= pkt->left )
return -1; 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 ) else if( i_replicated_data_length == 1 )
{ {
/* i_media_object_offset is presentation time */ /* i_media_object_offset is presentation time */
...@@ -692,23 +701,21 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa ...@@ -692,23 +701,21 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
} }
else 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? if (i_base_pts < 0) i_base_pts = 0; // FIXME?
i_base_pts *= 1000; i_base_pts *= 1000;
uint32_t i_payload_data_length = 0;
uint32_t i_temp_payload_length = 0;
if( pkt->multiple ) { if( pkt->multiple ) {
if (GetValue2b(&i_temp_payload_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->length_type) < 0) if (GetValue2b(&i_temp_payload_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->length_type) < 0)
return -1; return -1;
} else } else
i_temp_payload_length = pkt->length - pkt->padding_length - pkt->i_skip; 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 #ifdef ASF_DEBUG
...@@ -720,6 +727,12 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa ...@@ -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 ); " pts=%"PRId64" st=%"PRIu32, i_base_pts, pkt->send_time );
#endif #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]; asf_track_t *tk = p_sys->track[i_stream_number];
if( tk == NULL ) if( tk == NULL )
{ {
...@@ -746,6 +759,10 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa ...@@ -746,6 +759,10 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
if( !tk->p_es ) if( !tk->p_es )
goto skip; 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; uint32_t i_subpayload_count = 0;
while (i_payload_data_length) while (i_payload_data_length)
{ {
...@@ -896,7 +913,10 @@ static int DemuxPacket( demux_t *p_demux ) ...@@ -896,7 +913,10 @@ static int DemuxPacket( demux_t *p_demux )
for( int i_payload = 0; i_payload < i_payload_count ; i_payload++ ) for( int i_payload = 0; i_payload < i_payload_count ; i_payload++ )
if (DemuxPayload(p_demux, &pkt, i_payload) < 0) if (DemuxPayload(p_demux, &pkt, i_payload) < 0)
{
msg_Warn( p_demux, "payload err %d / %d", i_payload + 1, i_payload_count );
return 0; return 0;
}
if( pkt.left > 0 ) if( pkt.left > 0 )
{ {
...@@ -1320,6 +1340,7 @@ static int DemuxInit( demux_t *p_demux ) ...@@ -1320,6 +1340,7 @@ static int DemuxInit( demux_t *p_demux )
msg_Dbg( p_demux, "ignoring unknown stream(ID:%d)", msg_Dbg( p_demux, "ignoring unknown stream(ID:%d)",
p_sp->i_stream_number ); p_sp->i_stream_number );
} }
es_format_Clean( &fmt ); es_format_Clean( &fmt );
} }
......
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