@ -39,12 +39,20 @@
# define KEYFRAMES_TIMESTAMP_TAG "times"
# define KEYFRAMES_BYTEOFFSET_TAG "filepositions"
# define VALIDATE_INDEX_TS_THRESH 2500
typedef struct {
int wrong_dts ; ///< wrong dts due to negative cts
uint8_t * new_extradata [ 2 ] ;
int new_extradata_size [ 2 ] ;
int last_sample_rate ;
int last_channels ;
struct {
int64_t dts ;
int64_t pos ;
} validate_index [ 2 ] ;
int validate_next ;
int validate_count ;
} FLVContext ;
static int flv_probe ( AVProbeData * p )
@ -137,6 +145,7 @@ static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize) {
}
static int parse_keyframes_index ( AVFormatContext * s , AVIOContext * ioc , AVStream * vstream , int64_t max_pos ) {
FLVContext * flv = s - > priv_data ;
unsigned int arraylen = 0 , timeslen = 0 , fileposlen = 0 , i ;
double num_val ;
char str_val [ 256 ] ;
@ -206,11 +215,17 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream
}
}
if ( ! ret & & timeslen = = fileposlen )
for ( i = 0 ; i < fileposlen ; i + + )
if ( ! ret & & timeslen = = fileposlen ) {
for ( i = 0 ; i < fileposlen ; i + + ) {
av_add_index_entry ( vstream , filepositions [ i ] , times [ i ] * 1000 ,
0 , 0 , AVINDEX_KEYFRAME ) ;
else
if ( i < 2 ) {
flv - > validate_index [ i ] . pos = filepositions [ i ] ;
flv - > validate_index [ i ] . dts = times [ i ] * 1000 ;
flv - > validate_count = i + 1 ;
}
}
} else
av_log ( s , AV_LOG_WARNING , " Invalid keyframes object, skipping. \n " ) ;
finish :
@ -434,6 +449,22 @@ static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream,
return 0 ;
}
static void clear_index_entries ( AVFormatContext * s , int64_t pos )
{
int i , j , out ;
av_log ( s , AV_LOG_WARNING , " Found invalid index entries, clearing the index. \n " ) ;
for ( i = 0 ; i < s - > nb_streams ; i + + ) {
AVStream * st = s - > streams [ i ] ;
/* Remove all index entries that point to >= pos */
out = 0 ;
for ( j = 0 ; j < st - > nb_index_entries ; j + + ) {
if ( st - > index_entries [ j ] . pos < pos )
st - > index_entries [ out + + ] = st - > index_entries [ j ] ;
}
st - > nb_index_entries = out ;
}
}
static int flv_read_packet ( AVFormatContext * s , AVPacket * pkt )
{
FLVContext * flv = s - > priv_data ;
@ -455,6 +486,22 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
avio_skip ( s - > pb , 3 ) ; /* stream id, always 0 */
flags = 0 ;
if ( flv - > validate_next < flv - > validate_count ) {
int64_t validate_pos = flv - > validate_index [ flv - > validate_next ] . pos ;
if ( pos = = validate_pos ) {
if ( FFABS ( dts - flv - > validate_index [ flv - > validate_next ] . dts ) < =
VALIDATE_INDEX_TS_THRESH ) {
flv - > validate_next + + ;
} else {
clear_index_entries ( s , validate_pos ) ;
flv - > validate_count = 0 ;
}
} else if ( pos > validate_pos ) {
clear_index_entries ( s , validate_pos ) ;
flv - > validate_count = 0 ;
}
}
if ( size = = 0 )
continue ;
@ -633,6 +680,8 @@ leave:
static int flv_read_seek ( AVFormatContext * s , int stream_index ,
int64_t ts , int flags )
{
FLVContext * flv = s - > priv_data ;
flv - > validate_count = 0 ;
return avio_seek_time ( s - > pb , stream_index , ts , flags ) ;
}