static int write_abst(AVFormatContext *s, OutputStream *os, int final)
{
    HDSContext *c = s->priv_data;
    AVIOContext *out;
    char filename[1024], temp_filename[1024];
    int i, ret;
    int64_t asrt_pos, afrt_pos;
    int start = 0, fragments;
    int index = s->streams[os->first_stream]->id;
    int64_t cur_media_time = 0;
    if (c->window_size)
        start = FFMAX(os->nb_fragments - c->window_size, 0);
    fragments = os->nb_fragments - start;
    if (final)
        cur_media_time = os->last_ts;
    else if (os->nb_fragments)
        cur_media_time = os->fragments[os->nb_fragments - 1]->start_time;

    snprintf(filename, sizeof(filename),
             "%s/stream%d.abst", s->filename, index);
    snprintf(temp_filename, sizeof(temp_filename),
             "%s/stream%d.abst.tmp", s->filename, index);
    ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
    if (ret < 0) {
        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
        return ret;
    }
    avio_wb32(out, 0); // abst size
    avio_wl32(out, MKTAG('a','b','s','t'));
    avio_wb32(out, 0); // version + flags
    avio_wb32(out, os->fragment_index - 1); // BootstrapinfoVersion
    avio_w8(out, final ? 0 : 0x20); // profile, live, update
    avio_wb32(out, 1000); // timescale
    avio_wb64(out, cur_media_time);
    avio_wb64(out, 0); // SmpteTimeCodeOffset
    avio_w8(out, 0); // MovieIdentifer (null string)
    avio_w8(out, 0); // ServerEntryCount
    avio_w8(out, 0); // QualityEntryCount
    avio_w8(out, 0); // DrmData (null string)
    avio_w8(out, 0); // MetaData (null string)
    avio_w8(out, 1); // SegmentRunTableCount
    asrt_pos = avio_tell(out);
    avio_wb32(out, 0); // asrt size
    avio_wl32(out, MKTAG('a','s','r','t'));
    avio_wb32(out, 0); // version + flags
    avio_w8(out, 0); // QualityEntryCount
    avio_wb32(out, 1); // SegmentRunEntryCount
    avio_wb32(out, 1); // FirstSegment
    avio_wb32(out, final ? (os->fragment_index - 1) : 0xffffffff); // FragmentsPerSegment
    update_size(out, asrt_pos);
    avio_w8(out, 1); // FragmentRunTableCount
    afrt_pos = avio_tell(out);
    avio_wb32(out, 0); // afrt size
    avio_wl32(out, MKTAG('a','f','r','t'));
    avio_wb32(out, 0); // version + flags
    avio_wb32(out, 1000); // timescale
    avio_w8(out, 0); // QualityEntryCount
    avio_wb32(out, fragments); // FragmentRunEntryCount
    for (i = start; i < os->nb_fragments; i++) {
        avio_wb32(out, os->fragments[i]->n);
        avio_wb64(out, os->fragments[i]->start_time);
        avio_wb32(out, os->fragments[i]->duration);
    }
    update_size(out, afrt_pos);
    update_size(out, 0);
    ff_format_io_close(s, &out);
    return ff_rename(temp_filename, filename);
}