@ -82,6 +82,7 @@ typedef struct HLSContext {
char * segment_filename ;
int use_localtime ; ///< flag to expand filename with localtime
int use_localtime_mkdir ; ///< flag to mkdir dirname in timebased filename
int allowcache ;
int64_t recording_time ;
int has_video ;
@ -304,16 +305,35 @@ static int hls_mux_init(AVFormatContext *s)
}
/* Create a new segment and append it to the segment list */
static int hls_append_segment ( HLSContext * hls , double duration , int64_t pos ,
int64_t size )
static int hls_append_segment ( struct AVFormatContext * s , HLSContext * hls , double duration ,
int64_t pos , int64_t size )
{
HLSSegment * en = av_malloc ( sizeof ( * en ) ) ;
char * tmp , * p ;
const char * pl_dir , * filename ;
int ret ;
if ( ! en )
return AVERROR ( ENOMEM ) ;
av_strlcpy ( en - > filename , av_basename ( hls - > avf - > filename ) , sizeof ( en - > filename ) ) ;
filename = av_basename ( hls - > avf - > filename ) ;
if ( hls - > use_localtime_mkdir ) {
/* Possibly prefix with mkdir'ed subdir, if playlist share same
* base path . */
tmp = av_strdup ( s - > filename ) ;
if ( ! tmp ) {
av_free ( en ) ;
return AVERROR ( ENOMEM ) ;
}
pl_dir = av_dirname ( tmp ) ;
p = hls - > avf - > filename ;
if ( strstr ( p , pl_dir ) = = p )
filename = hls - > avf - > filename + strlen ( pl_dir ) + 1 ;
av_free ( tmp ) ;
}
av_strlcpy ( en - > filename , filename , sizeof ( en - > filename ) ) ;
if ( hls - > has_subtitle )
av_strlcpy ( en - > sub_filename , av_basename ( hls - > vtt_avf - > filename ) , sizeof ( en - > sub_filename ) ) ;
@ -508,7 +528,22 @@ static int hls_start(AVFormatContext *s)
av_log ( oc , AV_LOG_ERROR , " Could not get segment filename with use_localtime \n " ) ;
return AVERROR ( EINVAL ) ;
}
} else if ( av_get_frame_filename ( oc - > filename , sizeof ( oc - > filename ) ,
if ( c - > use_localtime_mkdir ) {
const char * dir ;
char * fn_copy = av_strdup ( oc - > filename ) ;
if ( ! fn_copy ) {
return AVERROR ( ENOMEM ) ;
}
dir = av_dirname ( fn_copy ) ;
if ( mkdir ( dir , 0777 ) = = - 1 & & errno ! = EEXIST ) {
av_log ( oc , AV_LOG_ERROR , " Could not create directory %s with use_localtime_mkdir \n " , dir ) ;
av_free ( fn_copy ) ;
return AVERROR ( errno ) ;
}
av_free ( fn_copy ) ;
}
} else if ( av_get_frame_filename ( oc - > filename , sizeof ( oc - > filename ) ,
c - > basename , c - > wrap ? c - > sequence % c - > wrap : c - > sequence ) < 0 ) {
av_log ( oc , AV_LOG_ERROR , " Invalid segment filename template '%s' you can try use -use_localtime 1 with it \n " , c - > basename ) ;
return AVERROR ( EINVAL ) ;
@ -778,7 +813,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
new_start_pos = avio_tell ( hls - > avf - > pb ) ;
hls - > size = new_start_pos - hls - > start_pos ;
ret = hls_append_segment ( hls , hls - > duration , hls - > start_pos , hls - > size ) ;
ret = hls_append_segment ( s , hls , hls - > duration , hls - > start_pos , hls - > size ) ;
hls - > start_pos = new_start_pos ;
if ( ret < 0 )
return ret ;
@ -825,7 +860,7 @@ static int hls_write_trailer(struct AVFormatContext *s)
if ( oc - > pb ) {
hls - > size = avio_tell ( hls - > avf - > pb ) - hls - > start_pos ;
ff_format_io_close ( s , & oc - > pb ) ;
hls_append_segment ( hls , hls - > duration , hls - > start_pos , hls - > size ) ;
hls_append_segment ( s , hls , hls - > duration , hls - > start_pos , hls - > size ) ;
}
if ( vtt_oc ) {
@ -871,7 +906,8 @@ static const AVOption options[] = {
{ " round_durations " , " round durations in m3u8 to whole numbers " , 0 , AV_OPT_TYPE_CONST , { . i64 = HLS_ROUND_DURATIONS } , 0 , UINT_MAX , E , " flags " } ,
{ " discont_start " , " start the playlist with a discontinuity tag " , 0 , AV_OPT_TYPE_CONST , { . i64 = HLS_DISCONT_START } , 0 , UINT_MAX , E , " flags " } ,
{ " omit_endlist " , " Do not append an endlist when ending stream " , 0 , AV_OPT_TYPE_CONST , { . i64 = HLS_OMIT_ENDLIST } , 0 , UINT_MAX , E , " flags " } ,
{ " use_localtime " , " set filename expansion with strftime at segment creation " , OFFSET ( use_localtime ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , E } ,
{ " use_localtime " , " set filename expansion with strftime at segment creation " , OFFSET ( use_localtime ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , E } ,
{ " use_localtime_mkdir " , " create last directory component in strftime-generated filename " , OFFSET ( use_localtime_mkdir ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , E } ,
{ " method " , " set the HTTP method " , OFFSET ( method ) , AV_OPT_TYPE_STRING , { . str = NULL } , 0 , 0 , E } ,
{ NULL } ,