@ -75,6 +75,8 @@ typedef struct HLSSegment {
int discont ;
int64_t pos ;
int64_t size ;
int64_t keyframe_pos ;
int64_t keyframe_size ;
unsigned var_stream_idx ;
char key_uri [ LINE_BUFFER_SIZE + 1 ] ;
@ -99,6 +101,7 @@ typedef enum HLSFlags {
HLS_TEMP_FILE = ( 1 < < 11 ) ,
HLS_PERIODIC_REKEY = ( 1 < < 12 ) ,
HLS_INDEPENDENT_SEGMENTS = ( 1 < < 13 ) ,
HLS_I_FRAMES_ONLY = ( 1 < < 14 ) ,
} HLSFlags ;
typedef enum {
@ -125,6 +128,9 @@ typedef struct VariantStream {
double dpp ; // duration per packet
int64_t start_pts ;
int64_t end_pts ;
int64_t video_lastpos ;
int64_t video_keyframe_pos ;
int64_t video_keyframe_size ;
double duration ; // last segment duration computed so far, in seconds
int64_t start_pos ; // last segment starting position
int64_t size ; // last segment size
@ -994,6 +1000,8 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls,
en - > duration = duration ;
en - > pos = pos ;
en - > size = size ;
en - > keyframe_pos = vs - > video_keyframe_pos ;
en - > keyframe_size = vs - > video_keyframe_size ;
en - > next = NULL ;
en - > discont = 0 ;
@ -1411,7 +1419,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
vs - > discontinuity_set = 0 ;
ff_hls_write_playlist_header ( hls - > m3u8_out , hls - > version , hls - > allowcache ,
target_duration , sequence , hls - > pl_type ) ;
target_duration , sequence , hls - > pl_type , hls - > flags & HLS_I_FRAMES_ONLY ) ;
if ( ( hls - > flags & HLS_DISCONT_START ) & & sequence = = hls - > start_sequence & & vs - > discontinuity_set = = 0 ) {
avio_printf ( hls - > m3u8_out , " #EXT-X-DISCONTINUITY \n " ) ;
@ -1439,7 +1447,7 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
ret = ff_hls_write_file_entry ( hls - > m3u8_out , en - > discont , byterange_mode ,
en - > duration , hls - > flags & HLS_ROUND_DURATIONS ,
en - > size , en - > pos , vs - > baseurl ,
en - > filename , prog_date_time_p ) ;
en - > filename , prog_date_time_p , en - > keyframe_size , en - > keyframe_pos , hls - > flags & HLS_I_FRAMES_ONLY ) ;
if ( ret < 0 ) {
av_log ( s , AV_LOG_WARNING , " ff_hls_write_file_entry get error \n " ) ;
}
@ -1455,11 +1463,11 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
goto fail ;
}
ff_hls_write_playlist_header ( hls - > sub_m3u8_out , hls - > version , hls - > allowcache ,
target_duration , sequence , PLAYLIST_TYPE_NONE ) ;
target_duration , sequence , PLAYLIST_TYPE_NONE , 0 ) ;
for ( en = vs - > segments ; en ; en = en - > next ) {
ret = ff_hls_write_file_entry ( hls - > sub_m3u8_out , 0 , byterange_mode ,
en - > duration , 0 , en - > size , en - > pos ,
vs - > baseurl , en - > sub_filename , NULL ) ;
vs - > baseurl , en - > sub_filename , NULL , 0 , 0 , 0 ) ;
if ( ret < 0 ) {
av_log ( s , AV_LOG_WARNING , " ff_hls_write_file_entry get error \n " ) ;
}
@ -2205,7 +2213,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
vs - > start_pts = pkt - > pts ;
}
if ( vs - > has_video ) {
if ( vs - > has_video ) {
can_split = st - > codecpar - > codec_type = = AVMEDIA_TYPE_VIDEO & &
( ( pkt - > flags & AV_PKT_FLAG_KEY ) | | ( hls - > flags & HLS_SPLIT_BY_TIME ) ) ;
is_ref_pkt = ( st - > codecpar - > codec_type = = AVMEDIA_TYPE_VIDEO ) & & ( pkt - > stream_index = = vs - > reference_stream_index ) ;
@ -2240,6 +2248,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
av_write_frame ( vs - > avf , NULL ) ; /* Flush any buffered data */
new_start_pos = avio_tell ( vs - > avf - > pb ) ;
if ( hls - > segment_type ! = SEGMENT_TYPE_FMP4 ) {
avio_flush ( oc - > pb ) ;
vs - > size = new_start_pos - vs - > start_pos ;
@ -2368,6 +2377,13 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
vs - > packets_written + + ;
if ( oc - > pb ) {
ret = ff_write_chained ( oc , stream_index , pkt , s , 0 ) ;
if ( ( st - > codecpar - > codec_type = = AVMEDIA_TYPE_VIDEO ) & & ( pkt - > flags & AV_PKT_FLAG_KEY ) ) {
vs - > video_keyframe_size = avio_tell ( oc - > pb ) - vs - > video_lastpos ;
vs - > video_keyframe_pos = vs - > start_pos ;
} else {
vs - > video_lastpos = avio_tell ( oc - > pb ) ;
}
if ( hls - > ignore_io_errors )
ret = 0 ;
}
@ -2919,6 +2935,7 @@ static const AVOption options[] = {
{ " second_level_segment_size " , " include segment size in segment filenames when use_localtime " , 0 , AV_OPT_TYPE_CONST , { . i64 = HLS_SECOND_LEVEL_SEGMENT_SIZE } , 0 , UINT_MAX , E , " flags " } ,
{ " periodic_rekey " , " reload keyinfo file periodically for re-keying " , 0 , AV_OPT_TYPE_CONST , { . i64 = HLS_PERIODIC_REKEY } , 0 , UINT_MAX , E , " flags " } ,
{ " independent_segments " , " add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable " , 0 , AV_OPT_TYPE_CONST , { . i64 = HLS_INDEPENDENT_SEGMENTS } , 0 , UINT_MAX , E , " flags " } ,
{ " iframes_only " , " add EXT-X-I-FRAMES-ONLY, whenever applicable " , 0 , AV_OPT_TYPE_CONST , { . i64 = HLS_I_FRAMES_ONLY } , 0 , UINT_MAX , E , " flags " } ,
# if FF_API_HLS_USE_LOCALTIME
{ " use_localtime " , " set filename expansion with strftime at segment creation(will be deprecated ) " , OFFSET ( use_localtime ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , E } ,
# endif