static int write_manifest(AVFormatContext *s, int final)
{
    HDSContext *c = s->priv_data;
    AVIOContext *out;
    char filename[1024], temp_filename[1024];
    int ret, i;
    float duration = 0;

    if (c->nb_streams > 0)
        duration = c->streams[0].last_ts * av_q2d(s->streams[0]->time_base);

    snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename);
    snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.tmp", s->filename);
    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_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
    avio_printf(out, "<manifest xmlns=\"http://ns.adobe.com/f4m/1.0\">\n");
    avio_printf(out, "\t<id>%s</id>\n", av_basename(s->filename));
    avio_printf(out, "\t<streamType>%s</streamType>\n",
                     final ? "recorded" : "live");
    avio_printf(out, "\t<deliveryType>streaming</deliveryType>\n");
    if (final)
        avio_printf(out, "\t<duration>%f</duration>\n", duration);
    for (i = 0; i < c->nb_streams; i++) {
        OutputStream *os = &c->streams[i];
        int b64_size = AV_BASE64_SIZE(os->metadata_size);
        char *base64 = av_malloc(b64_size);
        if (!base64) {
            ff_format_io_close(s, &out);
            return AVERROR(ENOMEM);
        }
        av_base64_encode(base64, b64_size, os->metadata, os->metadata_size);

        avio_printf(out, "\t<bootstrapInfo profile=\"named\" url=\"stream%d.abst\" id=\"bootstrap%d\" />\n", i, i);
        avio_printf(out, "\t<media bitrate=\"%d\" url=\"stream%d\" bootstrapInfoId=\"bootstrap%d\">\n", os->bitrate/1000, i, i);
        avio_printf(out, "\t\t<metadata>%s</metadata>\n", base64);
        avio_printf(out, "\t</media>\n");
        av_free(base64);
    }
    avio_printf(out, "</manifest>\n");
    avio_flush(out);
    ff_format_io_close(s, &out);
    return ff_rename(temp_filename, filename);
}