static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)

{

    MatroskaMuxContext *mkv = s->priv_data;

    int codec_type          = s->streams[pkt->stream_index]->codec->codec_type;

    int keyframe            = !!(pkt->flags & AV_PKT_FLAG_KEY);

    int cluster_size;

    int cluster_size_limit;

    int64_t cluster_time;

    int64_t cluster_time_limit;

    AVIOContext *pb;

    int ret;



    if (mkv->tracks[pkt->stream_index].write_dts)

        cluster_time = pkt->dts - mkv->cluster_pts;

    else

        cluster_time = pkt->pts - mkv->cluster_pts;



    // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or

    // after 4k and on a keyframe

    if (s->pb->seekable) {

        pb = s->pb;

        cluster_size = avio_tell(pb) - mkv->cluster_pos;

        cluster_time_limit = 5000;

        cluster_size_limit = 5 * 1024 * 1024;

    } else {

        pb = mkv->dyn_bc;

        cluster_size = avio_tell(pb);

        cluster_time_limit = 1000;

        cluster_size_limit = 32 * 1024;

    }



    if (mkv->cluster_pos &&

        (cluster_size > cluster_size_limit ||

         cluster_time > cluster_time_limit ||

         (codec_type == AVMEDIA_TYPE_VIDEO && keyframe &&

          cluster_size > 4 * 1024))) {

        av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64

               " bytes, pts %" PRIu64 "dts %" PRIu64 "\n",

               avio_tell(pb), pkt->pts, pkt->dts);

        end_ebml_master(pb, mkv->cluster);

        mkv->cluster_pos = 0;

        if (mkv->dyn_bc)

            mkv_flush_dynbuf(s);

    }



    // check if we have an audio packet cached

    if (mkv->cur_audio_pkt.size > 0) {

        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);

        av_free_packet(&mkv->cur_audio_pkt);

        if (ret < 0) {

            av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);

            return ret;

        }

    }



    // buffer an audio packet to ensure the packet containing the video

    // keyframe's timecode is contained in the same cluster for WebM

    if (codec_type == AVMEDIA_TYPE_AUDIO) {

        mkv->cur_audio_pkt = *pkt;

        if (pkt->buf) {

            mkv->cur_audio_pkt.buf = av_buffer_ref(pkt->buf);

            ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM);

        } else

            ret = av_dup_packet(&mkv->cur_audio_pkt);

    } else

        ret = mkv_write_packet_internal(s, pkt);

    return ret;

}

static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)

{

    MatroskaMuxContext *mkv = s->priv_data;

    int codec_type          = s->streams[pkt->stream_index]->codec->codec_type;

    int keyframe            = !!(pkt->flags & AV_PKT_FLAG_KEY);

    int cluster_size;

    int cluster_size_limit;

    int64_t cluster_time;

    int64_t cluster_time_limit;

    AVIOContext *pb;

    int ret;



    if (mkv->tracks[pkt->stream_index].write_dts)

        cluster_time = pkt->dts - mkv->cluster_pts;

    else

        cluster_time = pkt->pts - mkv->cluster_pts;



    

    

    if (s->pb->seekable) {

        pb = s->pb;

        cluster_size = avio_tell(pb) - mkv->cluster_pos;

        cluster_time_limit = 5000;

        cluster_size_limit = 5 * 1024 * 1024;

    } else {

        pb = mkv->dyn_bc;

        cluster_size = avio_tell(pb);

        cluster_time_limit = 1000;

        cluster_size_limit = 32 * 1024;

    }



    if (mkv->cluster_pos &&

        (cluster_size > cluster_size_limit ||

         cluster_time > cluster_time_limit ||

         (codec_type == AVMEDIA_TYPE_VIDEO && keyframe &&

          cluster_size > 4 * 1024))) {

        av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64

               " bytes, pts %" PRIu64 "dts %" PRIu64 "\n",

               avio_tell(pb), pkt->pts, pkt->dts);

        end_ebml_master(pb, mkv->cluster);

        mkv->cluster_pos = 0;

        if (mkv->dyn_bc)

            mkv_flush_dynbuf(s);

    }



    

    if (mkv->cur_audio_pkt.size > 0) {

        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);

        av_free_packet(&mkv->cur_audio_pkt);

        if (ret < 0) {

            av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);

            return ret;

        }

    }



    

    

    if (codec_type == AVMEDIA_TYPE_AUDIO) {

        mkv->cur_audio_pkt = *pkt;

        if (pkt->buf) {

            mkv->cur_audio_pkt.buf = av_buffer_ref(pkt->buf);

            ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM);

        } else

            ret = av_dup_packet(&mkv->cur_audio_pkt);

    } else

        ret = mkv_write_packet_internal(s, pkt);

    return ret;

}

static int FUNC_0(AVFormatContext *VAR_0, AVPacket *VAR_1)

{

    MatroskaMuxContext *mkv = VAR_0->priv_data;

    int VAR_2          = VAR_0->streams[VAR_1->stream_index]->codec->VAR_2;

    int VAR_3            = !!(VAR_1->flags & AV_PKT_FLAG_KEY);

    int VAR_4;

    int VAR_5;

    int64_t cluster_time;

    int64_t cluster_time_limit;

    AVIOContext *pb;

    int VAR_6;



    if (mkv->tracks[VAR_1->stream_index].write_dts)

        cluster_time = VAR_1->dts - mkv->cluster_pts;

    else

        cluster_time = VAR_1->pts - mkv->cluster_pts;



    

    

    if (VAR_0->pb->seekable) {

        pb = VAR_0->pb;

        VAR_4 = avio_tell(pb) - mkv->cluster_pos;

        cluster_time_limit = 5000;

        VAR_5 = 5 * 1024 * 1024;

    } else {

        pb = mkv->dyn_bc;

        VAR_4 = avio_tell(pb);

        cluster_time_limit = 1000;

        VAR_5 = 32 * 1024;

    }



    if (mkv->cluster_pos &&

        (VAR_4 > VAR_5 ||

         cluster_time > cluster_time_limit ||

         (VAR_2 == AVMEDIA_TYPE_VIDEO && VAR_3 &&

          VAR_4 > 4 * 1024))) {

        av_log(VAR_0, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64

               " bytes, pts %" PRIu64 "dts %" PRIu64 "\n",

               avio_tell(pb), VAR_1->pts, VAR_1->dts);

        end_ebml_master(pb, mkv->cluster);

        mkv->cluster_pos = 0;

        if (mkv->dyn_bc)

            mkv_flush_dynbuf(VAR_0);

    }



    

    if (mkv->cur_audio_pkt.size > 0) {

        VAR_6 = mkv_write_packet_internal(VAR_0, &mkv->cur_audio_pkt);

        av_free_packet(&mkv->cur_audio_pkt);

        if (VAR_6 < 0) {

            av_log(VAR_0, AV_LOG_ERROR, "Could not write cached audio packet VAR_6:%d\n", VAR_6);

            return VAR_6;

        }

    }



    

    

    if (VAR_2 == AVMEDIA_TYPE_AUDIO) {

        mkv->cur_audio_pkt = *VAR_1;

        if (VAR_1->buf) {

            mkv->cur_audio_pkt.buf = av_buffer_ref(VAR_1->buf);

            VAR_6 = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM);

        } else

            VAR_6 = av_dup_packet(&mkv->cur_audio_pkt);

    } else

        VAR_6 = mkv_write_packet_internal(VAR_0, VAR_1);

    return VAR_6;

}

static int FUNC_0(AVFormatContext *VAR_0, AVPacket *VAR_1)
{ MatroskaMuxContext *mkv = VAR_0->priv_data; int VAR_2          = VAR_0->streams[VAR_1->stream_index]->codec->VAR_2; int VAR_3            = !!(VAR_1->flags & AV_PKT_FLAG_KEY); int VAR_4; int VAR_5; int64_t cluster_time; int64_t cluster_time_limit; AVIOContext *pb; int VAR_6; if (mkv->tracks[VAR_1->stream_index].write_dts)
cluster_time = VAR_1->dts - mkv->cluster_pts; else
cluster_time = VAR_1->pts - mkv->cluster_pts; if (VAR_0->pb->seekable) { pb = VAR_0->pb; VAR_4 = avio_tell(pb) - mkv->cluster_pos; cluster_time_limit = 5000; VAR_5 = 5 * 1024 * 1024; } else { pb = mkv->dyn_bc; VAR_4 = avio_tell(pb); cluster_time_limit = 1000; VAR_5 = 32 * 1024; } if (mkv->cluster_pos &&
(VAR_4 > VAR_5 ||
cluster_time > cluster_time_limit ||
(VAR_2 == AVMEDIA_TYPE_VIDEO && VAR_3 &&
VAR_4 > 4 * 1024))) { av_log(VAR_0, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
" bytes, pts %" PRIu64 "dts %" PRIu64 "\n",
avio_tell(pb), VAR_1->pts, VAR_1->dts); end_ebml_master(pb, mkv->cluster); mkv->cluster_pos = 0; if (mkv->dyn_bc)
mkv_flush_dynbuf(VAR_0); } if (mkv->cur_audio_pkt.size > 0) { VAR_6 = mkv_write_packet_internal(VAR_0, &mkv->cur_audio_pkt); av_free_packet(&mkv->cur_audio_pkt); if (VAR_6 < 0) { av_log(VAR_0, AV_LOG_ERROR, "Could not write cached audio packet VAR_6:%d\n", VAR_6); return VAR_6; } } if (VAR_2 == AVMEDIA_TYPE_AUDIO) { mkv->cur_audio_pkt = *VAR_1; if (VAR_1->buf) { mkv->cur_audio_pkt.buf = av_buffer_ref(VAR_1->buf); VAR_6 = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM); } else VAR_6 = av_dup_packet(&mkv->cur_audio_pkt); } else VAR_6 = mkv_write_packet_internal(VAR_0, VAR_1); return VAR_6; }