@ -76,7 +76,7 @@ typedef struct OutputStream {
int nb_segments , segments_size , segment_index ;
int nb_segments , segments_size , segment_index ;
Segment * * segments ;
Segment * * segments ;
int64_t first_pts , start_pts , max_pts ;
int64_t first_pts , start_pts , max_pts ;
int64_t last_dts ;
int64_t last_dts , last_pts ;
int bit_rate ;
int bit_rate ;
char codec_str [ 100 ] ;
char codec_str [ 100 ] ;
@ -123,6 +123,7 @@ typedef struct DASHContext {
AVIOContext * m3u8_out ;
AVIOContext * m3u8_out ;
int streaming ;
int streaming ;
int64_t timeout ;
int64_t timeout ;
int index_correction ;
} DASHContext ;
} DASHContext ;
static struct codec_string {
static struct codec_string {
@ -1060,7 +1061,7 @@ static int dash_write_header(AVFormatContext *s)
static int add_segment ( OutputStream * os , const char * file ,
static int add_segment ( OutputStream * os , const char * file ,
int64_t time , int duration ,
int64_t time , int duration ,
int64_t start_pos , int64_t range_length ,
int64_t start_pos , int64_t range_length ,
int64_t index_length )
int64_t index_length , int next_exp_index )
{
{
int err ;
int err ;
Segment * seg ;
Segment * seg ;
@ -1088,6 +1089,12 @@ static int add_segment(OutputStream *os, const char *file,
seg - > index_length = index_length ;
seg - > index_length = index_length ;
os - > segments [ os - > nb_segments + + ] = seg ;
os - > segments [ os - > nb_segments + + ] = seg ;
os - > segment_index + + ;
os - > segment_index + + ;
//correcting the segment index if it has fallen behind the expected value
if ( os - > segment_index < next_exp_index ) {
av_log ( NULL , AV_LOG_WARNING , " Correcting the segment index after file %s: current=%d corrected=%d \n " ,
file , os - > segment_index , next_exp_index ) ;
os - > segment_index = next_exp_index ;
}
return 0 ;
return 0 ;
}
}
@ -1177,10 +1184,22 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
const char * proto = avio_find_protocol_name ( s - > url ) ;
const char * proto = avio_find_protocol_name ( s - > url ) ;
int use_rename = proto & & ! strcmp ( proto , " file " ) ;
int use_rename = proto & & ! strcmp ( proto , " file " ) ;
int cur_flush_segment_index = 0 ;
int cur_flush_segment_index = 0 , next_exp_index = - 1 ;
if ( stream > = 0 )
if ( stream > = 0 ) {
cur_flush_segment_index = c - > streams [ stream ] . segment_index ;
cur_flush_segment_index = c - > streams [ stream ] . segment_index ;
//finding the next segment's expected index, based on the current pts value
if ( c - > use_template & & ! c - > use_timeline & & c - > index_correction & &
c - > streams [ stream ] . last_pts ! = AV_NOPTS_VALUE & &
c - > streams [ stream ] . first_pts ! = AV_NOPTS_VALUE ) {
int64_t pts_diff = av_rescale_q ( c - > streams [ stream ] . last_pts -
c - > streams [ stream ] . first_pts ,
s - > streams [ stream ] - > time_base ,
AV_TIME_BASE_Q ) ;
next_exp_index = ( pts_diff / c - > seg_duration ) + 1 ;
}
}
for ( i = 0 ; i < s - > nb_streams ; i + + ) {
for ( i = 0 ; i < s - > nb_streams ; i + + ) {
OutputStream * os = & c - > streams [ i ] ;
OutputStream * os = & c - > streams [ i ] ;
AVStream * st = s - > streams [ i ] ;
AVStream * st = s - > streams [ i ] ;
@ -1240,7 +1259,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
if ( bitrate > = 0 )
if ( bitrate > = 0 )
os - > bit_rate = bitrate ;
os - > bit_rate = bitrate ;
}
}
add_segment ( os , os - > filename , os - > start_pts , os - > max_pts - os - > start_pts , os - > pos , range_length , index_length ) ;
add_segment ( os , os - > filename , os - > start_pts , os - > max_pts - os - > start_pts , os - > pos , range_length , index_length , next_exp_index ) ;
av_log ( s , AV_LOG_VERBOSE , " Representation %d media segment %d written to: %s \n " , i , os - > segment_index , os - > full_path ) ;
av_log ( s , AV_LOG_VERBOSE , " Representation %d media segment %d written to: %s \n " , i , os - > segment_index , os - > full_path ) ;
os - > pos + = range_length ;
os - > pos + = range_length ;
@ -1303,6 +1322,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
if ( os - > first_pts = = AV_NOPTS_VALUE )
if ( os - > first_pts = = AV_NOPTS_VALUE )
os - > first_pts = pkt - > pts ;
os - > first_pts = pkt - > pts ;
os - > last_pts = pkt - > pts ;
if ( ! c - > availability_start_time [ 0 ] )
if ( ! c - > availability_start_time [ 0 ] )
format_date_now ( c - > availability_start_time ,
format_date_now ( c - > availability_start_time ,
@ -1485,6 +1505,7 @@ static const AVOption options[] = {
{ " hls_playlist " , " Generate HLS playlist files(master.m3u8, media_%d.m3u8) " , OFFSET ( hls_playlist ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , E } ,
{ " hls_playlist " , " Generate HLS playlist files(master.m3u8, media_%d.m3u8) " , OFFSET ( hls_playlist ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , E } ,
{ " streaming " , " Enable/Disable streaming mode of output. Each frame will be moof fragment " , OFFSET ( streaming ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , E } ,
{ " streaming " , " Enable/Disable streaming mode of output. Each frame will be moof fragment " , OFFSET ( streaming ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , E } ,
{ " timeout " , " set timeout for socket I/O operations " , OFFSET ( timeout ) , AV_OPT_TYPE_DURATION , { . i64 = - 1 } , - 1 , INT_MAX , . flags = E } ,
{ " timeout " , " set timeout for socket I/O operations " , OFFSET ( timeout ) , AV_OPT_TYPE_DURATION , { . i64 = - 1 } , - 1 , INT_MAX , . flags = E } ,
{ " index_correction " , " Enable/Disable segment index correction logic " , OFFSET ( index_correction ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , E } ,
{ NULL } ,
{ NULL } ,
} ;
} ;