static int mov_flush_fragment(AVFormatContext *s)

{

    MOVMuxContext *mov = s->priv_data;

    int i, first_track = -1;

    int64_t mdat_size = 0;



    if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))

        return 0;



    if (mov->fragments == 0) {

        int64_t pos = avio_tell(s->pb);

        uint8_t *buf;

        int buf_size, moov_size;



        for (i = 0; i < mov->nb_streams; i++)

            if (!mov->tracks[i].entry)

                break;

        

        if (i < mov->nb_streams)

            return 0;



        moov_size = get_moov_size(s);

        for (i = 0; i < mov->nb_streams; i++)

            mov->tracks[i].data_offset = pos + moov_size + 8;



        if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)

            mov_write_identification(s->pb, s);

        mov_write_moov_tag(s->pb, mov, s);



        if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) {

            if (mov->flags & FF_MOV_FLAG_FASTSTART)

                mov->reserved_moov_pos = avio_tell(s->pb);

            avio_flush(s->pb);

            mov->fragments++;

            return 0;

        }



        buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);

        mov->mdat_buf = NULL;

        avio_wb32(s->pb, buf_size + 8);

        ffio_wfourcc(s->pb, "mdat");

        avio_write(s->pb, buf, buf_size);

        av_free(buf);



        mov->fragments++;

        mov->mdat_size = 0;

        for (i = 0; i < mov->nb_streams; i++) {

            if (mov->tracks[i].entry)

                mov->tracks[i].frag_start += mov->tracks[i].start_dts +

                                             mov->tracks[i].track_duration -

                                             mov->tracks[i].cluster[0].dts;

            mov->tracks[i].entry = 0;

        }

        avio_flush(s->pb);

        return 0;

    }



    for (i = 0; i < mov->nb_streams; i++) {

        MOVTrack *track = &mov->tracks[i];

        if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF)

            track->data_offset = 0;

        else

            track->data_offset = mdat_size;

        if (!track->mdat_buf)

            continue;

        mdat_size += avio_tell(track->mdat_buf);

        if (first_track < 0)

            first_track = i;

    }



    if (!mdat_size)

        return 0;



    for (i = 0; i < mov->nb_streams; i++) {

        MOVTrack *track = &mov->tracks[i];

        int buf_size, write_moof = 1, moof_tracks = -1;

        uint8_t *buf;

        int64_t duration = 0;



        if (track->entry)

            duration = track->start_dts + track->track_duration -

                       track->cluster[0].dts;

        if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) {

            if (!track->mdat_buf)

                continue;

            mdat_size = avio_tell(track->mdat_buf);

            moof_tracks = i;

        } else {

            write_moof = i == first_track;

        }



        if (write_moof) {

            avio_flush(s->pb);



            mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);

            mov->fragments++;



            avio_wb32(s->pb, mdat_size + 8);

            ffio_wfourcc(s->pb, "mdat");

        }



        if (track->entry)

            track->frag_start += duration;

        track->entry = 0;

        if (!track->mdat_buf)

            continue;

        buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);

        track->mdat_buf = NULL;



        avio_write(s->pb, buf, buf_size);

        av_free(buf);

    }



    mov->mdat_size = 0;



    avio_flush(s->pb);

    return 0;

}
