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);

    if ((hls->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) &&
        strlen(hls->current_segment_final_filename_fmt)) {
        char * old_filename = av_strdup(hls->avf->filename);  // %%s will be %s after strftime
        av_strlcpy(hls->avf->filename, hls->current_segment_final_filename_fmt, sizeof(hls->avf->filename));
        if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
            char * filename = av_strdup(hls->avf->filename);  // %%s will be %s after strftime
            if (!filename)
                return AVERROR(ENOMEM);
            if (replace_int_data_in_filename(hls->avf->filename, sizeof(hls->avf->filename),
                filename, 's', pos + size) < 1) {
                av_log(hls, 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);
                av_free(old_filename);
                return AVERROR(EINVAL);
            }
            av_free(filename);
        }
        if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) {
            char * filename = av_strdup(hls->avf->filename);  // %%t will be %t after strftime
            if (!filename)
                return AVERROR(ENOMEM);
            if (replace_int_data_in_filename(hls->avf->filename, sizeof(hls->avf->filename),
                filename, 't',  (int64_t)round(1000000 * duration)) < 1) {
                av_log(hls, 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);
                av_free(old_filename);
                return AVERROR(EINVAL);
            }
            av_free(filename);
        }
        ff_rename(old_filename, hls->avf->filename, hls);
        av_free(old_filename);
    }


    filename = av_basename(hls->avf->filename);

    if (hls->use_localtime_mkdir) {
        filename = hls->avf->filename;
    }
    if (find_segment_by_filename(hls->segments, filename)
        || find_segment_by_filename(hls->old_segments, filename)) {
        av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename);
    }
    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));
    else
        en->sub_filename[0] = '\0';

    en->duration = duration;
    en->pos      = pos;
    en->size     = size;
    en->next     = NULL;
    en->discont  = 0;

    if (hls->discontinuity) {
        en->discont = 1;
        hls->discontinuity = 0;
    }

    if (hls->key_info_file) {
        av_strlcpy(en->key_uri, hls->key_uri, sizeof(en->key_uri));
        av_strlcpy(en->iv_string, hls->iv_string, sizeof(en->iv_string));
    }

    if (!hls->segments)
        hls->segments = en;
    else
        hls->last_segment->next = en;

    hls->last_segment = en;

    // EVENT or VOD playlists imply sliding window cannot be used
    if (hls->pl_type != PLAYLIST_TYPE_NONE)
        hls->max_nb_segments = 0;

    if (hls->max_nb_segments && hls->nb_entries >= hls->max_nb_segments) {
        en = hls->segments;
        hls->initial_prog_date_time += en->duration;
        hls->segments = en->next;
        if (en && hls->flags & HLS_DELETE_SEGMENTS &&
                !(hls->flags & HLS_SINGLE_FILE || hls->wrap)) {
            en->next = hls->old_segments;
            hls->old_segments = en;
            if ((ret = hls_delete_old_segments(hls)) < 0)
                return ret;
        } else
            av_free(en);
    } else
        hls->nb_entries++;

    if (hls->max_seg_size > 0) {
        return 0;
    }
    hls->sequence++;

    return 0;
}