Commit 88ac075f authored by François Cartegnie's avatar François Cartegnie 🤞

demux: asf: split packet parsing for reuse

parent a61da5b4
......@@ -121,7 +121,9 @@ libdemux_stl_plugin_la_SOURCES = demux/stl.c
libdemux_stl_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
demux_LTLIBRARIES += libdemux_stl_plugin.la
libasf_plugin_la_SOURCES = demux/asf/asf.c demux/asf/libasf.c demux/asf/libasf.h demux/asf/libasf_guid.h
libasf_plugin_la_SOURCES = demux/asf/asf.c demux/asf/libasf.c demux/asf/libasf.h \
demux/asf/asfpacket.c demux/asf/asfpacket.h \
demux/asf/libasf_guid.h
demux_LTLIBRARIES += libasf_plugin.la
libavi_plugin_la_SOURCES = demux/avi/avi.c demux/avi/libavi.c demux/avi/libavi.h
......
......@@ -41,6 +41,7 @@
#include <limits.h>
#include "asfpacket.h"
#include "libasf.h"
#include "assert.h"
......@@ -75,6 +76,16 @@ static void FlushRemainingPackets( demux_t *p_demux );
#define MAX_ASF_TRACKS (ASF_MAX_STREAMNUMBER + 1)
#define ASF_PREROLL_FROM_CURRENT -1
/* callbacks for packet parser */
static void Packet_UpdateTime( asf_packet_sys_t *p_packetsys, uint8_t i_stream_number,
mtime_t i_time );
static asf_track_info_t * Packet_GetTrackInfo( asf_packet_sys_t *p_packetsys,
uint8_t i_stream_number );
static bool Packet_DoSkip( asf_packet_sys_t *p_packetsys, uint8_t i_stream_number, bool b_packet_keyframe );
static void Packet_Send(asf_packet_sys_t *p_packetsys, uint8_t i_stream_number, block_t **pp_frame);
static void Packet_SetAR( asf_packet_sys_t *p_packetsys, uint8_t i_stream_number,
uint8_t i_ratio_x, uint8_t i_ratio_y );
typedef struct
{
int i_cat;
......@@ -83,12 +94,10 @@ typedef struct
es_format_t *p_fmt; /* format backup for video changes */
bool b_selected;
asf_object_stream_properties_t *p_sp;
asf_object_extended_stream_properties_t *p_esp;
mtime_t i_time; /* track time*/
block_t *p_frame; /* use to gather complete frame */
asf_track_info_t info;
} asf_track_t;
struct demux_sys_t
......@@ -114,13 +123,14 @@ struct demux_sys_t
mtime_t i_preroll_start;
asf_packet_sys_t packet_sys;
vlc_meta_t *meta;
};
static mtime_t GetMoviePTS( demux_sys_t * );
static int DemuxInit( demux_t * );
static void DemuxEnd( demux_t * );
static int DemuxPacket( demux_t * );
/*****************************************************************************
* Open: check file and initializes ASF structures
......@@ -149,6 +159,16 @@ static int Open( vlc_object_t * p_this )
free( p_sys );
return VLC_EGENERIC;
}
p_sys->packet_sys.p_demux = p_demux;
p_sys->packet_sys.pi_preroll = &p_sys->p_fp->i_preroll;
p_sys->packet_sys.pi_preroll_start = &p_sys->i_preroll_start;
p_sys->packet_sys.pf_doskip = Packet_DoSkip;
p_sys->packet_sys.pf_send = Packet_Send;
p_sys->packet_sys.pf_gettrackinfo = Packet_GetTrackInfo;
p_sys->packet_sys.pf_updatetime = Packet_UpdateTime;
p_sys->packet_sys.pf_setaspectratio = Packet_SetAR;
return VLC_SUCCESS;
}
......@@ -222,7 +242,9 @@ static int Demux( demux_t *p_demux )
}
/* Read and demux a packet */
if( ( i_result = DemuxPacket( p_demux ) ) <= 0 )
if( ( i_result = DemuxASFPacket( &p_sys->packet_sys,
p_sys->p_fp->i_min_data_packet_size,
p_sys->p_fp->i_max_data_packet_size ) ) <= 0 )
{
FlushRemainingPackets( p_demux );
return i_result;
......@@ -275,9 +297,9 @@ static void WaitKeyframe( demux_t *p_demux )
for ( int i=0; i<MAX_ASF_TRACKS; i++ )
{
asf_track_t *tk = p_sys->track[i];
if ( tk && tk->p_sp && tk->i_cat == VIDEO_ES && tk->b_selected )
if ( tk && tk->info.p_sp && tk->i_cat == VIDEO_ES && tk->b_selected )
{
p_sys->i_seek_track = tk->p_sp->i_stream_number;
p_sys->i_seek_track = tk->info.p_sp->i_stream_number;
break;
}
}
......@@ -287,12 +309,12 @@ static void WaitKeyframe( demux_t *p_demux )
{
/* Skip forward at least 1 min */
asf_track_t *tk = p_sys->track[p_sys->i_seek_track];
if ( tk->p_esp && tk->p_esp->i_average_time_per_frame )
if ( tk->info.p_esp && tk->info.p_esp->i_average_time_per_frame )
{
/* 1 min if fastseek, otherwise 5 sec */
/* That's a guess for bandwidth */
uint64_t i_maxwaittime = ( p_sys->b_canfastseek ) ? 600000000 : 50000000;
i_maxwaittime /= tk->p_esp->i_average_time_per_frame;
i_maxwaittime /= tk->info.p_esp->i_average_time_per_frame;
p_sys->i_wait_keyframe = __MIN( i_maxwaittime, UINT_MAX );
}
else
......@@ -365,7 +387,7 @@ static void SeekPrepare( demux_t *p_demux )
demux_sys_t *p_sys = p_demux->p_sys;
p_sys->i_time = VLC_TS_INVALID;
p_sys->i_preroll_start = ASF_PREROLL_FROM_CURRENT;
p_sys->i_preroll_start = ASFPACKET_PREROLL_FROM_CURRENT;
for( int i = 0; i < MAX_ASF_TRACKS ; i++ )
{
asf_track_t *tk = p_sys->track[i];
......@@ -373,9 +395,9 @@ static void SeekPrepare( demux_t *p_demux )
continue;
tk->i_time = -1;
if( tk->p_frame )
block_ChainRelease( tk->p_frame );
tk->p_frame = NULL;
if( tk->info.p_frame )
block_ChainRelease( tk->info.p_frame );
tk->info.p_frame = NULL;
}
es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
......@@ -543,304 +565,52 @@ static mtime_t GetMoviePTS( demux_sys_t *p_sys )
return i_time;
}
static inline int GetValue2b(uint32_t *var, const uint8_t *p, unsigned int *skip, int left, int bits)
{
switch(bits&0x03)
{
case 1:
if (left < 1)
return -1;
*var = p[*skip]; *skip += 1;
return 0;
case 2:
if (left < 2)
return -1;
*var = GetWLE(&p[*skip]); *skip += 2;
return 0;
case 3:
if (left < 4)
return -1;
*var = GetDWLE(&p[*skip]); *skip += 4;
return 0;
case 0:
default:
return 0;
}
}
struct asf_packet_t
{
uint32_t property;
uint32_t length;
uint32_t padding_length;
uint32_t send_time;
bool multiple;
int length_type;
/* buffer handling for this ASF packet */
uint32_t i_skip;
const uint8_t *p_peek;
uint32_t left;
};
static void SendPacket(demux_t *p_demux, asf_track_t *tk)
static void Packet_SetAR( asf_packet_sys_t *p_packetsys, uint8_t i_stream_number,
uint8_t i_ratio_x, uint8_t i_ratio_y )
{
demux_sys_t *p_sys = p_demux->p_sys;
block_t *p_gather = block_ChainGather( tk->p_frame );
if( p_sys->i_time < VLC_TS_0 && tk->i_time > VLC_TS_INVALID )
{
p_sys->i_time = tk->i_time;
es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_time );
#ifdef ASF_DEBUG
msg_Dbg( p_demux, " setting PCR to %"PRId64, VLC_TS_0 + p_sys->i_time );
#endif
}
#ifdef ASF_DEBUG
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 );
tk->p_frame = NULL;
}
static int DemuxSubPayload(demux_t *p_demux, asf_track_t *tk,
uint32_t i_sub_payload_data_length, mtime_t i_pts, mtime_t i_dts,
uint32_t i_media_object_offset, bool b_keyframe )
{
/* FIXME I don't use i_media_object_number, sould I ? */
if( tk->p_frame && i_media_object_offset == 0 )
SendPacket(p_demux, tk);
block_t *p_frag = stream_Block( p_demux->s, i_sub_payload_data_length );
if( p_frag == NULL ) {
msg_Warn( p_demux, "cannot read data" );
return -1;
}
p_frag->i_pts = VLC_TS_0 + i_pts;
p_frag->i_dts = VLC_TS_0 + i_dts;
if ( b_keyframe )
p_frag->i_flags |= BLOCK_FLAG_TYPE_I;
block_ChainAppend( &tk->p_frame, p_frag );
return 0;
}
static uint32_t SkipBytes( stream_t *s, uint32_t i_bytes )
{
int i_read;
int i_to_read = __MIN(i_bytes, INT_MAX);
uint32_t i_bytes_read = 0;
demux_t *p_demux = p_packetsys->p_demux;
asf_track_t *tk = p_demux->p_sys->track[i_stream_number];
if ( tk->p_fmt->video.i_sar_num == i_ratio_x && tk->p_fmt->video.i_sar_den == i_ratio_y )
return;
while( i_bytes )
/* Only apply if origin pixel size >= 1x1, due to broken yacast */
if ( tk->p_fmt->video.i_height * i_ratio_x > tk->p_fmt->video.i_width * i_ratio_y )
{
i_read = stream_Read( s, NULL, i_to_read );
i_bytes -= i_read;
i_bytes_read += i_read;
if ( i_read < i_to_read || i_bytes == 0 )
vout_thread_t *p_vout = input_GetVout( p_demux->p_input );
if ( p_vout )
{
/* end of stream */
return i_bytes_read;
msg_Info( p_demux, "Changing aspect ratio to %i/%i", i_ratio_x, i_ratio_y );
vout_ChangeAspectRatio( p_vout, i_ratio_x, i_ratio_y );
vlc_object_release( p_vout );
}
i_to_read = __MIN(i_bytes, INT_MAX);
}
return i_bytes_read;
tk->p_fmt->video.i_sar_num = i_ratio_x;
tk->p_fmt->video.i_sar_den = i_ratio_y;
}
static void ParsePayloadExtensions(demux_t *p_demux, asf_track_t *tk,
const struct asf_packet_t *pkt,
uint32_t i_length, bool *b_keyframe )
static void Packet_UpdateTime( asf_packet_sys_t *p_packetsys, uint8_t i_stream_number,
mtime_t i_time )
{
if ( !tk || !tk->p_esp || !tk->p_esp->p_ext ) return;
const uint8_t *p_data = pkt->p_peek + pkt->i_skip + 8;
i_length -= 8;
uint16_t i_payload_extensions_size;
asf_payload_extension_system_t *p_ext = NULL;
/* Extensions always come in the declared order */
for ( int i=0; i< tk->p_esp->i_payload_extension_system_count; i++ )
{
p_ext = &tk->p_esp->p_ext[i];
if ( p_ext->i_data_size == 0xFFFF ) /* Variable length extension data */
{
if ( i_length < 2 ) return;
i_payload_extensions_size = GetWLE( p_data );
p_data += 2;
i_length -= 2;
i_payload_extensions_size = 0;
}
else
{
i_payload_extensions_size = p_ext->i_data_size;
}
if ( i_length < i_payload_extensions_size ) return;
if ( guidcmp( &p_ext->i_extension_id, &mfasf_sampleextension_outputcleanpoint_guid ) )
{
if ( i_payload_extensions_size != sizeof(uint8_t) ) goto sizeerror;
*b_keyframe |= *p_data;
}
else if ( guidcmp( &p_ext->i_extension_id, &asf_dvr_sampleextension_videoframe_guid ) )
{
if ( i_payload_extensions_size != sizeof(uint32_t) ) goto sizeerror;
uint32_t i_val = GetDWLE( p_data );
/* Valid keyframe must be a split frame start fragment */
*b_keyframe = i_val & ASF_EXTENSION_VIDEOFRAME_NEWFRAME;
if ( *b_keyframe )
{
/* And flagged as IFRAME */
*b_keyframe |= ( ( i_val & ASF_EXTENSION_VIDEOFRAME_TYPE_MASK )
== ASF_EXTENSION_VIDEOFRAME_IFRAME );
}
}
else if ( guidcmp( &p_ext->i_extension_id, &mfasf_sampleextension_pixelaspectratio_guid ) )
{
if ( i_payload_extensions_size != sizeof(uint16_t) ) goto sizeerror;
uint8_t i_ratio_x = *p_data;
uint8_t i_ratio_y = *(p_data + 1);
if ( tk->p_fmt->video.i_sar_num != i_ratio_x || tk->p_fmt->video.i_sar_den != i_ratio_y )
{
/* Only apply if origin pixel size >= 1x1, due to broken yacast */
if ( tk->p_fmt->video.i_height * i_ratio_x > tk->p_fmt->video.i_width * i_ratio_y )
{
vout_thread_t *p_vout = input_GetVout( p_demux->p_input );
if ( p_vout )
{
msg_Info( p_demux, "Changing aspect ratio to %i/%i", i_ratio_x, i_ratio_y );
vout_ChangeAspectRatio( p_vout, i_ratio_x, i_ratio_y );
vlc_object_release( p_vout );
}
}
tk->p_fmt->video.i_sar_num = i_ratio_x;
tk->p_fmt->video.i_sar_den = i_ratio_y;
}
}
i_length -= i_payload_extensions_size;
p_data += i_payload_extensions_size;
}
return;
asf_track_t *tk = p_packetsys->p_demux->p_sys->track[i_stream_number];
tk->i_time = i_time;
}
sizeerror:
msg_Warn( p_demux, "Unknown extension " GUID_FMT " data size of %u",
GUID_PRINT( p_ext->i_extension_id ), i_payload_extensions_size );
static asf_track_info_t * Packet_GetTrackInfo( asf_packet_sys_t *p_packetsys,
uint8_t i_stream_number )
{
return & p_packetsys->p_demux->p_sys->track[i_stream_number]->info;
}
static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payload)
static bool Packet_DoSkip( asf_packet_sys_t *p_packetsys, uint8_t i_stream_number, bool b_packet_keyframe )
{
#ifndef ASF_DEBUG
VLC_UNUSED( i_payload );
#endif
demux_t *p_demux = p_packetsys->p_demux;
demux_sys_t *p_sys = p_demux->p_sys;
const asf_track_t *tk = p_sys->track[i_stream_number];
if( ! pkt->left || pkt->i_skip >= pkt->left )
return -1;
bool b_packet_keyframe = pkt->p_peek[pkt->i_skip] >> 7;
uint8_t i_stream_number = pkt->p_peek[pkt->i_skip++] & 0x7f;
if ( i_stream_number >= MAX_ASF_TRACKS )
goto skip;
uint32_t i_media_object_number = 0;
if (GetValue2b(&i_media_object_number, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property >> 4) < 0)
return -1;
uint32_t i_media_object_offset = 0;
if (GetValue2b(&i_media_object_offset, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property >> 2) < 0)
return -1;
uint32_t i_replicated_data_length = 0;
if (GetValue2b(&i_replicated_data_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property) < 0)
return -1;
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;
p_sys->p_fp->i_preroll = __MIN( p_sys->p_fp->i_preroll, INT64_MAX );
/* First packet, in case we do not have index to guess preroll start time */
if ( p_sys->i_preroll_start == ASF_PREROLL_FROM_CURRENT )
p_sys->i_preroll_start = pkt->send_time * 1000;
/* Non compressed */
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 */
ParsePayloadExtensions( p_demux, p_sys->track[i_stream_number], pkt,
i_replicated_data_length, &b_packet_keyframe );
i_base_pts -= p_sys->p_fp->i_preroll;
pkt->i_skip += i_replicated_data_length;
if( ! pkt->left || pkt->i_skip >= pkt->left )
return -1;
}
else if ( i_replicated_data_length == 0 )
{
/* optional DWORDS missing */
i_base_pts = (mtime_t)pkt->send_time;
i_base_pts -= p_sys->p_fp->i_preroll;
}
/* Compressed payload */
else if( i_replicated_data_length == 1 )
{
/* i_media_object_offset is presentation time */
/* Next byte is Presentation Time Delta */
i_pts_delta = pkt->p_peek[pkt->i_skip];
i_base_pts = (mtime_t)i_media_object_offset;
i_base_pts -= p_sys->p_fp->i_preroll;
pkt->i_skip++;
i_media_object_offset = 0;
}
else
{
/* >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;
}
bool b_preroll_done = ( pkt->send_time > (p_sys->i_preroll_start/1000 + p_sys->p_fp->i_preroll) );
if (i_base_pts < 0) i_base_pts = 0; // FIXME?
i_base_pts *= 1000;
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;
i_payload_data_length = i_temp_payload_length;
#ifdef ASF_DEBUG
msg_Dbg( p_demux,
"payload(%d) stream_number:%"PRIu8" media_object_number:%d media_object_offset:%"PRIu32" replicated_data_length:%"PRIu32" payload_data_length %"PRIu32,
i_payload + 1, i_stream_number, i_media_object_number,
i_media_object_offset, i_replicated_data_length, i_payload_data_length );
msg_Dbg( p_demux,
" 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 )
{
msg_Warn( p_demux, "undeclared stream[Id 0x%x]", i_stream_number );
goto skip;
return true;
}
if( p_sys->i_wait_keyframe )
......@@ -850,226 +620,43 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
if ( !b_packet_keyframe )
{
p_sys->i_wait_keyframe--;
goto skip;
return true;
}
else
p_sys->i_wait_keyframe = 0;
}
else
goto skip;
return true;
}
if( !tk->p_es )
goto skip;
bool b_hugedelay = ( p_sys->p_fp->i_preroll * 1000 > CLOCK_FREQ * 3 );
if ( b_preroll_done || b_hugedelay )
{
if ( !b_hugedelay )
{
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;
}
else
tk->i_time = i_base_pts;
}
uint32_t i_subpayload_count = 0;
while (i_payload_data_length)
{
uint32_t i_sub_payload_data_length = i_payload_data_length;
if( i_replicated_data_length == 1 )
{
i_sub_payload_data_length = pkt->p_peek[pkt->i_skip++];
i_payload_data_length--;
}
SkipBytes( p_demux->s, pkt->i_skip );
mtime_t i_payload_pts = i_base_pts + (mtime_t)i_pts_delta * i_subpayload_count * 1000;
i_payload_pts -= tk->p_sp->i_time_offset * 10;
mtime_t i_payload_dts = INT64_C(1000) * pkt->send_time;
i_payload_dts -= p_sys->p_fp->i_preroll * 1000;
i_payload_dts -= tk->p_sp->i_time_offset * 10;
if ( b_hugedelay )
i_payload_dts = i_base_pts;
return true;
if ( i_sub_payload_data_length &&
DemuxSubPayload(p_demux, tk, i_sub_payload_data_length,
i_payload_pts, i_payload_dts, i_media_object_offset,
b_packet_keyframe ) < 0)
return -1;
if ( pkt->left > pkt->i_skip + i_sub_payload_data_length )
pkt->left -= pkt->i_skip + i_sub_payload_data_length;
else
pkt->left = 0;
pkt->i_skip = 0;
if( pkt->left > 0 )
{
int i_return = stream_Peek( p_demux->s, &pkt->p_peek, __MIN(pkt->left, INT_MAX) );
if ( i_return <= 0 || (unsigned int) i_return < __MIN(pkt->left, INT_MAX) )
{
msg_Warn( p_demux, "cannot peek, EOF ?" );
return -1;
}
}
if ( i_sub_payload_data_length <= i_payload_data_length )
i_payload_data_length -= i_sub_payload_data_length;
else
i_payload_data_length = 0;
i_subpayload_count++;
}
return 0;
skip:
pkt->i_skip += i_payload_data_length;
return 0;
return false;
}
static int DemuxPacket( demux_t *p_demux )
static void Packet_Send(asf_packet_sys_t *p_packetsys, uint8_t i_stream_number, block_t **pp_frame)
{
demux_t *p_demux = p_packetsys->p_demux;
demux_sys_t *p_sys = p_demux->p_sys;
const asf_track_t *tk = p_sys->track[i_stream_number];
uint32_t i_data_packet_min = p_sys->p_fp->i_min_data_packet_size;
const uint8_t *p_peek;
int i_return = stream_Peek( p_demux->s, &p_peek,i_data_packet_min );
if( i_return <= 0 || ((unsigned int) i_return) < i_data_packet_min )
{
msg_Warn( p_demux, "cannot peek while getting new packet, EOF ?" );
return 0;
}
unsigned int i_skip = 0;
/* *** parse error correction if present *** */
if( p_peek[0]&0x80 )
{
unsigned int i_error_correction_data_length = p_peek[0] & 0x0f;
unsigned int i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01;
unsigned int i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03;
i_skip += 1; // skip error correction flags
if( i_error_correction_length_type != 0x00 ||
i_opaque_data_present != 0 ||
i_error_correction_data_length != 0x02 )
{
goto loop_error_recovery;
}
i_skip += i_error_correction_data_length;
}
else
msg_Warn( p_demux, "no error correction" );
/* sanity check */
if( i_skip + 2 >= i_data_packet_min )
goto loop_error_recovery;
struct asf_packet_t pkt;
int i_packet_flags = p_peek[i_skip]; i_skip++;
pkt.property = p_peek[i_skip]; i_skip++;
pkt.multiple = !!(i_packet_flags&0x01);
pkt.length = i_data_packet_min;
pkt.padding_length = 0;
if (GetValue2b(&pkt.length, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 5) < 0)
goto loop_error_recovery;
uint32_t i_packet_sequence;
if (GetValue2b(&i_packet_sequence, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 1) < 0)
goto loop_error_recovery;
if (GetValue2b(&pkt.padding_length, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 3) < 0)
goto loop_error_recovery;
if( pkt.padding_length > pkt.length )
{
msg_Warn( p_demux, "Too large padding: %"PRIu32, pkt.padding_length );
goto loop_error_recovery;
}
if( pkt.length < i_data_packet_min )
{
/* if packet length too short, there is extra padding */
pkt.padding_length += i_data_packet_min - pkt.length;
pkt.length = i_data_packet_min;
}
block_t *p_gather = block_ChainGather( *pp_frame );
pkt.send_time = GetDWLE( p_peek + i_skip ); i_skip += 4;
/* uint16_t i_packet_duration = GetWLE( p_peek + i_skip ); */ i_skip += 2;
i_return = stream_Peek( p_demux->s, &p_peek, pkt.length );
if( i_return <= 0 || pkt.length == 0 || (unsigned int)i_return < pkt.length )
{
msg_Warn( p_demux, "cannot peek, EOF ?" );
return 0;
}
int i_payload_count = 1;
pkt.length_type = 0x02; //unused
if( pkt.multiple )
if( p_sys->i_time < VLC_TS_0 && tk->i_time > VLC_TS_INVALID )
{
i_payload_count = p_peek[i_skip] & 0x3f;
pkt.length_type = ( p_peek[i_skip] >> 6 )&0x03;
i_skip++;
}
p_sys->i_time = tk->i_time;
es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_time );
#ifdef ASF_DEBUG
msg_Dbg(p_demux, "%d payloads", i_payload_count);
msg_Dbg( p_demux, " setting PCR to %"PRId64, VLC_TS_0 + p_sys->i_time );
#endif
}
pkt.i_skip = i_skip;
pkt.p_peek = p_peek;
pkt.left = pkt.length;
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;