@ -470,17 +470,9 @@ static HLSSegment *find_segment_by_filename(HLSSegment *segment, const char *fil
return ( HLSSegment * ) NULL ;
}
/* Create a new segment and append it to the segment list */
static int hls_append_segment ( struct AVFormatContext * s , HLSContext * hls , double duration ,
int64_t pos , int64_t size )
static int sls_flags_filename_process ( struct AVFormatContext * s , HLSContext * hls , HLSSegment * en , double duration ,
int64_t pos , int64_t size )
{
HLSSegment * en = av_malloc ( sizeof ( * en ) ) ;
const char * filename ;
int ret ;
if ( ! en )
return AVERROR ( ENOMEM ) ;
if ( ( hls - > flags & ( HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION ) ) & &
strlen ( hls - > current_segment_final_filename_fmt ) ) {
av_strlcpy ( hls - > avf - > filename , hls - > current_segment_final_filename_fmt , sizeof ( hls - > avf - > filename ) ) ;
@ -521,7 +513,127 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double
av_free ( filename ) ;
}
}
return 0 ;
}
static int sls_flag_check_duration_size_index ( HLSContext * hls )
{
int ret = 0 ;
if ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_DURATION ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_duration hls_flag requires use_localtime to be true \n " ) ;
ret = AVERROR ( EINVAL ) ;
}
if ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_SIZE ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_size hls_flag requires use_localtime to be true \n " ) ;
ret = AVERROR ( EINVAL ) ;
}
if ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_INDEX ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_index hls_flag requires use_localtime to be true \n " ) ;
ret = AVERROR ( EINVAL ) ;
}
return ret ;
}
static int sls_flag_check_duration_size ( HLSContext * hls )
{
const char * proto = avio_find_protocol_name ( hls - > basename ) ;
int segment_renaming_ok = proto & & ! strcmp ( proto , " file " ) ;
int ret = 0 ;
if ( ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_DURATION ) & & ! segment_renaming_ok ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_duration hls_flag works only with file protocol segment names \n " ) ;
ret = AVERROR ( EINVAL ) ;
}
if ( ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_SIZE ) & & ! segment_renaming_ok ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_size hls_flag works only with file protocol segment names \n " ) ;
ret = AVERROR ( EINVAL ) ;
}
return ret ;
}
static void sls_flag_file_rename ( HLSContext * hls , char * old_filename ) {
if ( ( hls - > flags & ( HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION ) ) & &
strlen ( hls - > current_segment_final_filename_fmt ) ) {
ff_rename ( old_filename , hls - > avf - > filename , hls ) ;
}
}
static int sls_flag_use_localtime_filename ( AVFormatContext * oc , HLSContext * c )
{
if ( c - > flags & HLS_SECOND_LEVEL_SEGMENT_INDEX ) {
char * filename = av_strdup ( oc - > filename ) ; // %%d will be %d after strftime
if ( ! filename )
return AVERROR ( ENOMEM ) ;
if ( replace_int_data_in_filename ( oc - > filename , sizeof ( oc - > filename ) ,
# if FF_API_HLS_WRAP
filename , ' d ' , c - > wrap ? c - > sequence % c - > wrap : c - > sequence ) < 1 ) {
# else
filename , ' d ' , c - > sequence ) < 1 ) {
# endif
av_log ( c , AV_LOG_ERROR , " Invalid second level segment filename template '%s', "
" you can try to remove second_level_segment_index flag \n " ,
filename ) ;
av_free ( filename ) ;
return AVERROR ( EINVAL ) ;
}
av_free ( filename ) ;
}
if ( c - > flags & ( HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION ) ) {
av_strlcpy ( c - > current_segment_final_filename_fmt , oc - > filename ,
sizeof ( c - > current_segment_final_filename_fmt ) ) ;
if ( c - > flags & HLS_SECOND_LEVEL_SEGMENT_SIZE ) {
char * filename = av_strdup ( oc - > filename ) ; // %%s will be %s after strftime
if ( ! filename )
return AVERROR ( ENOMEM ) ;
if ( replace_int_data_in_filename ( oc - > filename , sizeof ( oc - > filename ) , filename , ' s ' , 0 ) < 1 ) {
av_log ( c , AV_LOG_ERROR , " Invalid second level segment filename template '%s', "
" you can try to remove second_level_segment_size flag \n " ,
filename ) ;
av_free ( filename ) ;
return AVERROR ( EINVAL ) ;
}
av_free ( filename ) ;
}
if ( c - > flags & HLS_SECOND_LEVEL_SEGMENT_DURATION ) {
char * filename = av_strdup ( oc - > filename ) ; // %%t will be %t after strftime
if ( ! filename )
return AVERROR ( ENOMEM ) ;
if ( replace_int_data_in_filename ( oc - > filename , sizeof ( oc - > filename ) , filename , ' t ' , 0 ) < 1 ) {
av_log ( c , AV_LOG_ERROR , " Invalid second level segment filename template '%s', "
" you can try to remove second_level_segment_time flag \n " ,
filename ) ;
av_free ( filename ) ;
return AVERROR ( EINVAL ) ;
}
av_free ( filename ) ;
}
}
return 0 ;
}
/* Create a new segment and append it to the segment list */
static int hls_append_segment ( struct AVFormatContext * s , HLSContext * hls , double duration ,
int64_t pos , int64_t size )
{
HLSSegment * en = av_malloc ( sizeof ( * en ) ) ;
const char * filename ;
int ret ;
if ( ! en )
return AVERROR ( ENOMEM ) ;
ret = sls_flags_filename_process ( s , hls , en , duration , pos , size ) ;
if ( ret < 0 ) {
return ret ;
}
filename = av_basename ( hls - > avf - > filename ) ;
@ -870,57 +982,12 @@ static int hls_start(AVFormatContext *s)
av_log ( oc , AV_LOG_ERROR , " Could not get segment filename with use_localtime \n " ) ;
return AVERROR ( EINVAL ) ;
}
if ( c - > flags & HLS_SECOND_LEVEL_SEGMENT_INDEX ) {
char * filename = av_strdup ( oc - > filename ) ; // %%d will be %d after strftime
if ( ! filename )
return AVERROR ( ENOMEM ) ;
if ( replace_int_data_in_filename ( oc - > filename , sizeof ( oc - > filename ) ,
# if FF_API_HLS_WRAP
filename , ' d ' , c - > wrap ? c - > sequence % c - > wrap : c - > sequence ) < 1 ) {
# else
filename , ' d ' , c - > sequence ) < 1 ) {
# endif
av_log ( c , AV_LOG_ERROR ,
" Invalid second level segment filename template '%s', "
" you can try to remove second_level_segment_index flag \n " ,
filename ) ;
av_free ( filename ) ;
return AVERROR ( EINVAL ) ;
}
av_free ( filename ) ;
}
if ( c - > flags & ( HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION ) ) {
av_strlcpy ( c - > current_segment_final_filename_fmt , oc - > filename ,
sizeof ( c - > current_segment_final_filename_fmt ) ) ;
if ( c - > flags & HLS_SECOND_LEVEL_SEGMENT_SIZE ) {
char * filename = av_strdup ( oc - > filename ) ; // %%s will be %s after strftime
if ( ! filename )
return AVERROR ( ENOMEM ) ;
if ( replace_int_data_in_filename ( oc - > filename , sizeof ( oc - > filename ) , filename , ' s ' , 0 ) < 1 ) {
av_log ( c , AV_LOG_ERROR ,
" Invalid second level segment filename template '%s', "
" you can try to remove second_level_segment_size flag \n " ,
filename ) ;
av_free ( filename ) ;
return AVERROR ( EINVAL ) ;
}
av_free ( filename ) ;
}
if ( c - > flags & HLS_SECOND_LEVEL_SEGMENT_DURATION ) {
char * filename = av_strdup ( oc - > filename ) ; // %%t will be %t after strftime
if ( ! filename )
return AVERROR ( ENOMEM ) ;
if ( replace_int_data_in_filename ( oc - > filename , sizeof ( oc - > filename ) , filename , ' t ' , 0 ) < 1 ) {
av_log ( c , AV_LOG_ERROR ,
" Invalid second level segment filename template '%s', "
" you can try to remove second_level_segment_time flag \n " ,
filename ) ;
av_free ( filename ) ;
return AVERROR ( EINVAL ) ;
}
av_free ( filename ) ;
}
err = sls_flag_use_localtime_filename ( oc , c ) ;
if ( err < 0 ) {
return AVERROR ( ENOMEM ) ;
}
if ( c - > use_localtime_mkdir ) {
const char * dir ;
char * fn_copy = av_strdup ( oc - > filename ) ;
@ -1043,7 +1110,8 @@ static int hls_write_header(AVFormatContext *s)
int basename_size ;
int vtt_basename_size ;
if ( hls - > start_sequence_source_type = = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH | | hls - > start_sequence_source_type = = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME ) {
if ( ( hls - > start_sequence_source_type = = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH ) | |
( hls - > start_sequence_source_type = = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME ) ) {
time_t t = time ( NULL ) ; // we will need it in either case
if ( hls - > start_sequence_source_type = = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH ) {
hls - > start_sequence = ( int64_t ) t ;
@ -1138,38 +1206,13 @@ static int hls_write_header(AVFormatContext *s)
}
}
if ( ! hls - > use_localtime ) {
if ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_DURATION ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_duration hls_flag requires use_localtime to be true \n " ) ;
ret = AVERROR ( EINVAL ) ;
goto fail ;
}
if ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_SIZE ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_size hls_flag requires use_localtime to be true \n " ) ;
ret = AVERROR ( EINVAL ) ;
ret = sls_flag_check_duration_size_index ( hls ) ;
if ( ret < 0 ) {
goto fail ;
}
if ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_INDEX ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_index hls_flag requires use_localtime to be true \n " ) ;
ret = AVERROR ( EINVAL ) ;
goto fail ;
}
} else {
const char * proto = avio_find_protocol_name ( hls - > basename ) ;
int segment_renaming_ok = proto & & ! strcmp ( proto , " file " ) ;
if ( ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_DURATION ) & & ! segment_renaming_ok ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_duration hls_flag works only with file protocol segment names \n " ) ;
ret = AVERROR ( EINVAL ) ;
goto fail ;
}
if ( ( hls - > flags & HLS_SECOND_LEVEL_SEGMENT_SIZE ) & & ! segment_renaming_ok ) {
av_log ( hls , AV_LOG_ERROR ,
" second_level_segment_size hls_flag works only with file protocol segment names \n " ) ;
ret = AVERROR ( EINVAL ) ;
ret = sls_flag_check_duration_size ( hls ) ;
if ( ret < 0 ) {
goto fail ;
}
}
@ -1355,10 +1398,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
} else if ( hls - > max_seg_size > 0 ) {
if ( hls - > start_pos > = hls - > max_seg_size ) {
hls - > sequence + + ;
if ( ( hls - > flags & ( HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION ) ) & &
strlen ( hls - > current_segment_final_filename_fmt ) ) {
ff_rename ( old_filename , hls - > avf - > filename , hls ) ;
}
sls_flag_file_rename ( hls , old_filename ) ;
ret = hls_start ( s ) ;
hls - > start_pos = 0 ;
/* When split segment by byte, the duration is short than hls_time,
@ -1367,11 +1407,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
}
hls - > number + + ;
} else {
if ( ( hls - > flags & ( HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION ) ) & &
strlen ( hls - > current_segment_final_filename_fmt ) ) {
ff_rename ( old_filename , hls - > avf - > filename , hls ) ;
}
sls_flag_file_rename ( hls , old_filename ) ;
ret = hls_start ( s ) ;
}
@ -1416,10 +1452,7 @@ static int hls_write_trailer(struct AVFormatContext *s)
hls_append_segment ( s , hls , hls - > duration + hls - > dpp , hls - > start_pos , hls - > size ) ;
}
if ( ( hls - > flags & ( HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION ) ) & &
strlen ( hls - > current_segment_final_filename_fmt ) ) {
ff_rename ( old_filename , hls - > avf - > filename , hls ) ;
}
sls_flag_file_rename ( hls , old_filename ) ;
if ( vtt_oc ) {
if ( vtt_oc - > pb )