static int mux_write_header(AVFormatContext *s)
{
    MXFContext *mxf = s->priv_data;
    ByteIOContext *pb = s->pb;
    int64_t header_metadata_start, offset_now;
    int i;

    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st = s->streams[i];
        MXFStreamContext *sc = av_mallocz(sizeof(MXFStreamContext));
        if (!sc)
            return AVERROR(ENOMEM);
        st->priv_data = sc;
        // set pts information
        if (st->codec->codec_type == CODEC_TYPE_VIDEO)
            av_set_pts_info(st, 64, 1, st->codec->time_base.den);
        else if (st->codec->codec_type == CODEC_TYPE_AUDIO)
            av_set_pts_info(st, 64, 1, st->codec->sample_rate);
        sc->essence_container_ul = mxf_get_essence_container_ul(st->codec->codec_id);
        if (!sc->essence_container_ul) {
            av_log(s, AV_LOG_ERROR, "track %d: could not find essence container ul, "
                   "codec not currently supported in container\n", i);
            return -1;
        }
    }

    mxf_write_partition(s, 0, 1, header_partition_key);

    // mark the start of the headermetadata and calculate metadata size
    header_metadata_start = url_ftell(s->pb);
    mxf_write_primer_pack(s);
    if (mxf_write_header_metadata_sets(s) < 0)
        goto fail;
    offset_now = url_ftell(s->pb);
    mxf->header_byte_count = offset_now - header_metadata_start;
    // update header_byte_count
    url_fseek(pb, mxf->header_byte_count_offset, SEEK_SET);
    put_be64(pb, mxf->header_byte_count);
    url_fseek(pb, offset_now, SEEK_SET);

    put_flush_packet(pb);
    return 0;
fail:
    mxf_free(s);
    return -1;
}