static int mkv_write_header(AVFormatContext *s)

{

    MatroskaMuxContext *mkv = s->priv_data;

    AVIOContext *pb = s->pb;

    ebml_master ebml_header;

    AVDictionaryEntry *tag;

    int ret, i, version = 2;

    int64_t creation_time;



    if (!strcmp(s->oformat->name, "webm"))

        mkv->mode = MODE_WEBM;

    else

        mkv->mode = MODE_MATROSKAv2;



    if (mkv->mode != MODE_WEBM ||

        av_dict_get(s->metadata, "stereo_mode", NULL, 0) ||

        av_dict_get(s->metadata, "alpha_mode", NULL, 0))

        version = 4;



    if (s->nb_streams > MAX_TRACKS) {

        av_log(s, AV_LOG_ERROR,

               "At most %d streams are supported for muxing in Matroska\n",

               MAX_TRACKS);

        return AVERROR(EINVAL);

    }



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

        if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_COOK ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RA_288 ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_SIPR ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV10 ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV20) {

            av_log(s, AV_LOG_ERROR,

                   "The Matroska muxer does not yet support muxing %s\n",

                   avcodec_get_name(s->streams[i]->codecpar->codec_id));

            return AVERROR_PATCHWELCOME;

        }

        if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_OPUS ||

            av_dict_get(s->streams[i]->metadata, "stereo_mode", NULL, 0) ||

            av_dict_get(s->streams[i]->metadata, "alpha_mode", NULL, 0))

            version = 4;

    }



    mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks));

    if (!mkv->tracks) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }

    ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0);

    put_ebml_uint   (pb, EBML_ID_EBMLVERSION        ,           1);

    put_ebml_uint   (pb, EBML_ID_EBMLREADVERSION    ,           1);

    put_ebml_uint   (pb, EBML_ID_EBMLMAXIDLENGTH    ,           4);

    put_ebml_uint   (pb, EBML_ID_EBMLMAXSIZELENGTH  ,           8);

    put_ebml_string (pb, EBML_ID_DOCTYPE            , s->oformat->name);

    put_ebml_uint   (pb, EBML_ID_DOCTYPEVERSION     ,     version);

    put_ebml_uint   (pb, EBML_ID_DOCTYPEREADVERSION ,           2);

    end_ebml_master(pb, ebml_header);



    mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0);

    mkv->segment_offset = avio_tell(pb);



    // we write 2 seek heads - one at the end of the file to point to each

    // cluster, and one at the beginning to point to all other level one

    // elements (including the seek head at the end of the file), which

    // isn't more than 10 elements if we only write one of each other

    // currently defined level 1 element

    mkv->main_seekhead    = mkv_start_seekhead(pb, mkv->segment_offset, 10);

    if (!mkv->main_seekhead) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }



    ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, avio_tell(pb));

    if (ret < 0) goto fail;



    ret = start_ebml_master_crc32(pb, &mkv->info_bc, mkv, &mkv->info, MATROSKA_ID_INFO, 0);

    if (ret < 0)

        return ret;

    pb = mkv->info_bc;



    put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);

    if ((tag = av_dict_get(s->metadata, "title", NULL, 0)))

        put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value);

    if (!(s->flags & AVFMT_FLAG_BITEXACT)) {

        put_ebml_string(pb, MATROSKA_ID_MUXINGAPP, LIBAVFORMAT_IDENT);

        if ((tag = av_dict_get(s->metadata, "encoding_tool", NULL, 0)))

            put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, tag->value);

        else

            put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);



        if (mkv->mode != MODE_WEBM) {

            uint32_t segment_uid[4];

            AVLFG lfg;



            av_lfg_init(&lfg, av_get_random_seed());



            for (i = 0; i < 4; i++)

                segment_uid[i] = av_lfg_get(&lfg);



            put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16);

        }

    } else {

        const char *ident = "Lavf";

        put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , ident);

        put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, ident);

    }



    if (ff_parse_creation_time_metadata(s, &creation_time, 0) > 0) {

        // Adjust time so it's relative to 2001-01-01 and convert to nanoseconds.

        int64_t date_utc = (creation_time - 978307200000000LL) * 1000;

        uint8_t date_utc_buf[8];

        AV_WB64(date_utc_buf, date_utc);

        put_ebml_binary(pb, MATROSKA_ID_DATEUTC, date_utc_buf, 8);

    }



    // reserve space for the duration

    mkv->duration = 0;

    mkv->duration_offset = avio_tell(pb);

    if (!mkv->is_live) {

        int64_t metadata_duration = get_metadata_duration(s);



        if (s->duration > 0) {

            int64_t scaledDuration = av_rescale(s->duration, 1000, AV_TIME_BASE);

            put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);

            av_log(s, AV_LOG_DEBUG, "Write early duration from recording time = %" PRIu64 "\n", scaledDuration);

        } else if (metadata_duration > 0) {

            int64_t scaledDuration = av_rescale(metadata_duration, 1000, AV_TIME_BASE);

            put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);

            av_log(s, AV_LOG_DEBUG, "Write early duration from metadata = %" PRIu64 "\n", scaledDuration);

        } else {

            put_ebml_void(pb, 11);              // assumes double-precision float to be written

        }

    }

    if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)

        end_ebml_master_crc32_preliminary(s->pb, &mkv->info_bc, mkv, mkv->info);

    else

        end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv, mkv->info);

    pb = s->pb;



    // initialize stream_duration fields

    mkv->stream_durations = av_mallocz(s->nb_streams * sizeof(int64_t));

    mkv->stream_duration_offsets = av_mallocz(s->nb_streams * sizeof(int64_t));



    ret = mkv_write_tracks(s);

    if (ret < 0)

        goto fail;



    for (i = 0; i < s->nb_chapters; i++)

        mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - s->chapters[i]->id);



    ret = mkv_write_chapters(s);

    if (ret < 0)

        goto fail;



    if (mkv->mode != MODE_WEBM) {

        ret = mkv_write_attachments(s);

        if (ret < 0)

            goto fail;

    }



    ret = mkv_write_tags(s);

    if (ret < 0)

        goto fail;



    if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)

        mkv_write_seekhead(pb, mkv);



    mkv->cues = mkv_start_cues(mkv->segment_offset);

    if (!mkv->cues) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }

    if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && mkv->reserve_cues_space) {

        mkv->cues_pos = avio_tell(pb);

        put_ebml_void(pb, mkv->reserve_cues_space);

    }



    av_init_packet(&mkv->cur_audio_pkt);

    mkv->cur_audio_pkt.size = 0;

    mkv->cluster_pos = -1;



    avio_flush(pb);



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

    // after 4k and on a keyframe

    if (pb->seekable & AVIO_SEEKABLE_NORMAL) {

        if (mkv->cluster_time_limit < 0)

            mkv->cluster_time_limit = 5000;

        if (mkv->cluster_size_limit < 0)

            mkv->cluster_size_limit = 5 * 1024 * 1024;

    } else {

        if (mkv->cluster_time_limit < 0)

            mkv->cluster_time_limit = 1000;

        if (mkv->cluster_size_limit < 0)

            mkv->cluster_size_limit = 32 * 1024;

    }



    return 0;

fail:

    mkv_free(mkv);

    return ret;

}

static int mkv_write_header(AVFormatContext *s)

{

    MatroskaMuxContext *mkv = s->priv_data;

    AVIOContext *pb = s->pb;

    ebml_master ebml_header;

    AVDictionaryEntry *tag;

    int ret, i, version = 2;

    int64_t creation_time;



    if (!strcmp(s->oformat->name, "webm"))

        mkv->mode = MODE_WEBM;

    else

        mkv->mode = MODE_MATROSKAv2;



    if (mkv->mode != MODE_WEBM ||

        av_dict_get(s->metadata, "stereo_mode", NULL, 0) ||

        av_dict_get(s->metadata, "alpha_mode", NULL, 0))

        version = 4;



    if (s->nb_streams > MAX_TRACKS) {

        av_log(s, AV_LOG_ERROR,

               "At most %d streams are supported for muxing in Matroska\n",

               MAX_TRACKS);

        return AVERROR(EINVAL);

    }



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

        if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_COOK ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RA_288 ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_SIPR ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV10 ||

            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV20) {

            av_log(s, AV_LOG_ERROR,

                   "The Matroska muxer does not yet support muxing %s\n",

                   avcodec_get_name(s->streams[i]->codecpar->codec_id));

            return AVERROR_PATCHWELCOME;

        }

        if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_OPUS ||

            av_dict_get(s->streams[i]->metadata, "stereo_mode", NULL, 0) ||

            av_dict_get(s->streams[i]->metadata, "alpha_mode", NULL, 0))

            version = 4;

    }



    mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks));

    if (!mkv->tracks) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }

    ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0);

    put_ebml_uint   (pb, EBML_ID_EBMLVERSION        ,           1);

    put_ebml_uint   (pb, EBML_ID_EBMLREADVERSION    ,           1);

    put_ebml_uint   (pb, EBML_ID_EBMLMAXIDLENGTH    ,           4);

    put_ebml_uint   (pb, EBML_ID_EBMLMAXSIZELENGTH  ,           8);

    put_ebml_string (pb, EBML_ID_DOCTYPE            , s->oformat->name);

    put_ebml_uint   (pb, EBML_ID_DOCTYPEVERSION     ,     version);

    put_ebml_uint   (pb, EBML_ID_DOCTYPEREADVERSION ,           2);

    end_ebml_master(pb, ebml_header);



    mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0);

    mkv->segment_offset = avio_tell(pb);



    

    

    

    

    

    mkv->main_seekhead    = mkv_start_seekhead(pb, mkv->segment_offset, 10);

    if (!mkv->main_seekhead) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }



    ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, avio_tell(pb));

    if (ret < 0) goto fail;



    ret = start_ebml_master_crc32(pb, &mkv->info_bc, mkv, &mkv->info, MATROSKA_ID_INFO, 0);

    if (ret < 0)

        return ret;

    pb = mkv->info_bc;



    put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);

    if ((tag = av_dict_get(s->metadata, "title", NULL, 0)))

        put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value);

    if (!(s->flags & AVFMT_FLAG_BITEXACT)) {

        put_ebml_string(pb, MATROSKA_ID_MUXINGAPP, LIBAVFORMAT_IDENT);

        if ((tag = av_dict_get(s->metadata, "encoding_tool", NULL, 0)))

            put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, tag->value);

        else

            put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);



        if (mkv->mode != MODE_WEBM) {

            uint32_t segment_uid[4];

            AVLFG lfg;



            av_lfg_init(&lfg, av_get_random_seed());



            for (i = 0; i < 4; i++)

                segment_uid[i] = av_lfg_get(&lfg);



            put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16);

        }

    } else {

        const char *ident = "Lavf";

        put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , ident);

        put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, ident);

    }



    if (ff_parse_creation_time_metadata(s, &creation_time, 0) > 0) {

        

        int64_t date_utc = (creation_time - 978307200000000LL) * 1000;

        uint8_t date_utc_buf[8];

        AV_WB64(date_utc_buf, date_utc);

        put_ebml_binary(pb, MATROSKA_ID_DATEUTC, date_utc_buf, 8);

    }



    

    mkv->duration = 0;

    mkv->duration_offset = avio_tell(pb);

    if (!mkv->is_live) {

        int64_t metadata_duration = get_metadata_duration(s);



        if (s->duration > 0) {

            int64_t scaledDuration = av_rescale(s->duration, 1000, AV_TIME_BASE);

            put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);

            av_log(s, AV_LOG_DEBUG, "Write early duration from recording time = %" PRIu64 "\n", scaledDuration);

        } else if (metadata_duration > 0) {

            int64_t scaledDuration = av_rescale(metadata_duration, 1000, AV_TIME_BASE);

            put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);

            av_log(s, AV_LOG_DEBUG, "Write early duration from metadata = %" PRIu64 "\n", scaledDuration);

        } else {

            put_ebml_void(pb, 11);              

        }

    }

    if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)

        end_ebml_master_crc32_preliminary(s->pb, &mkv->info_bc, mkv, mkv->info);

    else

        end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv, mkv->info);

    pb = s->pb;



    

    mkv->stream_durations = av_mallocz(s->nb_streams * sizeof(int64_t));

    mkv->stream_duration_offsets = av_mallocz(s->nb_streams * sizeof(int64_t));



    ret = mkv_write_tracks(s);

    if (ret < 0)

        goto fail;



    for (i = 0; i < s->nb_chapters; i++)

        mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - s->chapters[i]->id);



    ret = mkv_write_chapters(s);

    if (ret < 0)

        goto fail;



    if (mkv->mode != MODE_WEBM) {

        ret = mkv_write_attachments(s);

        if (ret < 0)

            goto fail;

    }



    ret = mkv_write_tags(s);

    if (ret < 0)

        goto fail;



    if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)

        mkv_write_seekhead(pb, mkv);



    mkv->cues = mkv_start_cues(mkv->segment_offset);

    if (!mkv->cues) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }

    if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && mkv->reserve_cues_space) {

        mkv->cues_pos = avio_tell(pb);

        put_ebml_void(pb, mkv->reserve_cues_space);

    }



    av_init_packet(&mkv->cur_audio_pkt);

    mkv->cur_audio_pkt.size = 0;

    mkv->cluster_pos = -1;



    avio_flush(pb);



    

    

    if (pb->seekable & AVIO_SEEKABLE_NORMAL) {

        if (mkv->cluster_time_limit < 0)

            mkv->cluster_time_limit = 5000;

        if (mkv->cluster_size_limit < 0)

            mkv->cluster_size_limit = 5 * 1024 * 1024;

    } else {

        if (mkv->cluster_time_limit < 0)

            mkv->cluster_time_limit = 1000;

        if (mkv->cluster_size_limit < 0)

            mkv->cluster_size_limit = 32 * 1024;

    }



    return 0;

fail:

    mkv_free(mkv);

    return ret;

}

static int FUNC_0(AVFormatContext *VAR_0)

{

    MatroskaMuxContext *mkv = VAR_0->priv_data;

    AVIOContext *pb = VAR_0->pb;

    ebml_master ebml_header;

    AVDictionaryEntry *tag;

    int VAR_1, VAR_2, VAR_3 = 2;

    int64_t creation_time;



    if (!strcmp(VAR_0->oformat->name, "webm"))

        mkv->mode = MODE_WEBM;

    else

        mkv->mode = MODE_MATROSKAv2;



    if (mkv->mode != MODE_WEBM ||

        av_dict_get(VAR_0->metadata, "stereo_mode", NULL, 0) ||

        av_dict_get(VAR_0->metadata, "alpha_mode", NULL, 0))

        VAR_3 = 4;



    if (VAR_0->nb_streams > MAX_TRACKS) {

        av_log(VAR_0, AV_LOG_ERROR,

               "At most %d streams are supported for muxing in Matroska\n",

               MAX_TRACKS);

        return AVERROR(EINVAL);

    }



    for (VAR_2 = 0; VAR_2 < VAR_0->nb_streams; VAR_2++) {

        if (VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 ||

            VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_COOK ||

            VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_RA_288 ||

            VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_SIPR ||

            VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_RV10 ||

            VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_RV20) {

            av_log(VAR_0, AV_LOG_ERROR,

                   "The Matroska muxer does not yet support muxing %VAR_0\n",

                   avcodec_get_name(VAR_0->streams[VAR_2]->codecpar->codec_id));

            return AVERROR_PATCHWELCOME;

        }

        if (VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_OPUS ||

            av_dict_get(VAR_0->streams[VAR_2]->metadata, "stereo_mode", NULL, 0) ||

            av_dict_get(VAR_0->streams[VAR_2]->metadata, "alpha_mode", NULL, 0))

            VAR_3 = 4;

    }



    mkv->tracks = av_mallocz_array(VAR_0->nb_streams, sizeof(*mkv->tracks));

    if (!mkv->tracks) {

        VAR_1 = AVERROR(ENOMEM);

        goto fail;

    }

    ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0);

    put_ebml_uint   (pb, EBML_ID_EBMLVERSION        ,           1);

    put_ebml_uint   (pb, EBML_ID_EBMLREADVERSION    ,           1);

    put_ebml_uint   (pb, EBML_ID_EBMLMAXIDLENGTH    ,           4);

    put_ebml_uint   (pb, EBML_ID_EBMLMAXSIZELENGTH  ,           8);

    put_ebml_string (pb, EBML_ID_DOCTYPE            , VAR_0->oformat->name);

    put_ebml_uint   (pb, EBML_ID_DOCTYPEVERSION     ,     VAR_3);

    put_ebml_uint   (pb, EBML_ID_DOCTYPEREADVERSION ,           2);

    end_ebml_master(pb, ebml_header);



    mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0);

    mkv->segment_offset = avio_tell(pb);



    

    

    

    

    

    mkv->main_seekhead    = mkv_start_seekhead(pb, mkv->segment_offset, 10);

    if (!mkv->main_seekhead) {

        VAR_1 = AVERROR(ENOMEM);

        goto fail;

    }



    VAR_1 = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, avio_tell(pb));

    if (VAR_1 < 0) goto fail;



    VAR_1 = start_ebml_master_crc32(pb, &mkv->info_bc, mkv, &mkv->info, MATROSKA_ID_INFO, 0);

    if (VAR_1 < 0)

        return VAR_1;

    pb = mkv->info_bc;



    put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);

    if ((tag = av_dict_get(VAR_0->metadata, "title", NULL, 0)))

        put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value);

    if (!(VAR_0->flags & AVFMT_FLAG_BITEXACT)) {

        put_ebml_string(pb, MATROSKA_ID_MUXINGAPP, LIBAVFORMAT_IDENT);

        if ((tag = av_dict_get(VAR_0->metadata, "encoding_tool", NULL, 0)))

            put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, tag->value);

        else

            put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);



        if (mkv->mode != MODE_WEBM) {

            uint32_t segment_uid[4];

            AVLFG lfg;



            av_lfg_init(&lfg, av_get_random_seed());



            for (VAR_2 = 0; VAR_2 < 4; VAR_2++)

                segment_uid[VAR_2] = av_lfg_get(&lfg);



            put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16);

        }

    } else {

        const char *VAR_4 = "Lavf";

        put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , VAR_4);

        put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, VAR_4);

    }



    if (ff_parse_creation_time_metadata(VAR_0, &creation_time, 0) > 0) {

        

        int64_t date_utc = (creation_time - 978307200000000LL) * 1000;

        uint8_t date_utc_buf[8];

        AV_WB64(date_utc_buf, date_utc);

        put_ebml_binary(pb, MATROSKA_ID_DATEUTC, date_utc_buf, 8);

    }



    

    mkv->duration = 0;

    mkv->duration_offset = avio_tell(pb);

    if (!mkv->is_live) {

        int64_t metadata_duration = get_metadata_duration(VAR_0);



        if (VAR_0->duration > 0) {

            int64_t scaledDuration = av_rescale(VAR_0->duration, 1000, AV_TIME_BASE);

            put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);

            av_log(VAR_0, AV_LOG_DEBUG, "Write early duration from recording time = %" PRIu64 "\n", scaledDuration);

        } else if (metadata_duration > 0) {

            int64_t scaledDuration = av_rescale(metadata_duration, 1000, AV_TIME_BASE);

            put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);

            av_log(VAR_0, AV_LOG_DEBUG, "Write early duration from metadata = %" PRIu64 "\n", scaledDuration);

        } else {

            put_ebml_void(pb, 11);              

        }

    }

    if ((VAR_0->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)

        end_ebml_master_crc32_preliminary(VAR_0->pb, &mkv->info_bc, mkv, mkv->info);

    else

        end_ebml_master_crc32(VAR_0->pb, &mkv->info_bc, mkv, mkv->info);

    pb = VAR_0->pb;



    

    mkv->stream_durations = av_mallocz(VAR_0->nb_streams * sizeof(int64_t));

    mkv->stream_duration_offsets = av_mallocz(VAR_0->nb_streams * sizeof(int64_t));



    VAR_1 = mkv_write_tracks(VAR_0);

    if (VAR_1 < 0)

        goto fail;



    for (VAR_2 = 0; VAR_2 < VAR_0->nb_chapters; VAR_2++)

        mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - VAR_0->chapters[VAR_2]->id);



    VAR_1 = mkv_write_chapters(VAR_0);

    if (VAR_1 < 0)

        goto fail;



    if (mkv->mode != MODE_WEBM) {

        VAR_1 = mkv_write_attachments(VAR_0);

        if (VAR_1 < 0)

            goto fail;

    }



    VAR_1 = mkv_write_tags(VAR_0);

    if (VAR_1 < 0)

        goto fail;



    if (!(VAR_0->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)

        mkv_write_seekhead(pb, mkv);



    mkv->cues = mkv_start_cues(mkv->segment_offset);

    if (!mkv->cues) {

        VAR_1 = AVERROR(ENOMEM);

        goto fail;

    }

    if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && mkv->reserve_cues_space) {

        mkv->cues_pos = avio_tell(pb);

        put_ebml_void(pb, mkv->reserve_cues_space);

    }



    av_init_packet(&mkv->cur_audio_pkt);

    mkv->cur_audio_pkt.size = 0;

    mkv->cluster_pos = -1;



    avio_flush(pb);



    

    

    if (pb->seekable & AVIO_SEEKABLE_NORMAL) {

        if (mkv->cluster_time_limit < 0)

            mkv->cluster_time_limit = 5000;

        if (mkv->cluster_size_limit < 0)

            mkv->cluster_size_limit = 5 * 1024 * 1024;

    } else {

        if (mkv->cluster_time_limit < 0)

            mkv->cluster_time_limit = 1000;

        if (mkv->cluster_size_limit < 0)

            mkv->cluster_size_limit = 32 * 1024;

    }



    return 0;

fail:

    mkv_free(mkv);

    return VAR_1;

}

static int FUNC_0(AVFormatContext *VAR_0)
{ MatroskaMuxContext *mkv = VAR_0->priv_data; AVIOContext *pb = VAR_0->pb; ebml_master ebml_header; AVDictionaryEntry *tag; int VAR_1, VAR_2, VAR_3 = 2; int64_t creation_time; if (!strcmp(VAR_0->oformat->name, "webm"))
mkv->mode = MODE_WEBM; else
mkv->mode = MODE_MATROSKAv2; if (mkv->mode != MODE_WEBM ||
av_dict_get(VAR_0->metadata, "stereo_mode", NULL, 0) ||
av_dict_get(VAR_0->metadata, "alpha_mode", NULL, 0))
VAR_3 = 4; if (VAR_0->nb_streams > MAX_TRACKS) { av_log(VAR_0, AV_LOG_ERROR,
"At most %d streams are supported for muxing in Matroska\n",
MAX_TRACKS); return AVERROR(EINVAL); } for (VAR_2 = 0; VAR_2 < VAR_0->nb_streams; VAR_2++) { if (VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 ||
VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_COOK ||
VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_RA_288 ||
VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_SIPR ||
VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_RV10 ||
VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_RV20) { av_log(VAR_0, AV_LOG_ERROR,
"The Matroska muxer does not yet support muxing %VAR_0\n",
avcodec_get_name(VAR_0->streams[VAR_2]->codecpar->codec_id)); return AVERROR_PATCHWELCOME; } if (VAR_0->streams[VAR_2]->codecpar->codec_id == AV_CODEC_ID_OPUS ||
av_dict_get(VAR_0->streams[VAR_2]->metadata, "stereo_mode", NULL, 0) ||
av_dict_get(VAR_0->streams[VAR_2]->metadata, "alpha_mode", NULL, 0))
VAR_3 = 4; } mkv->tracks = av_mallocz_array(VAR_0->nb_streams, sizeof(*mkv->tracks)); if (!mkv->tracks) { VAR_1 = AVERROR(ENOMEM); goto fail; } ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0); put_ebml_uint   (pb, EBML_ID_EBMLVERSION        ,           1); put_ebml_uint   (pb, EBML_ID_EBMLREADVERSION    ,           1); put_ebml_uint   (pb, EBML_ID_EBMLMAXIDLENGTH    ,           4); put_ebml_uint   (pb, EBML_ID_EBMLMAXSIZELENGTH  ,           8); put_ebml_string (pb, EBML_ID_DOCTYPE            , VAR_0->oformat->name); put_ebml_uint   (pb, EBML_ID_DOCTYPEVERSION     ,     VAR_3); put_ebml_uint   (pb, EBML_ID_DOCTYPEREADVERSION ,           2); end_ebml_master(pb, ebml_header); mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0); mkv->segment_offset = avio_tell(pb); mkv->main_seekhead    = mkv_start_seekhead(pb, mkv->segment_offset, 10); if (!mkv->main_seekhead) { VAR_1 = AVERROR(ENOMEM); goto fail; } VAR_1 = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, avio_tell(pb)); if (VAR_1 < 0) goto fail; VAR_1 = start_ebml_master_crc32(pb, &mkv->info_bc, mkv, &mkv->info, MATROSKA_ID_INFO, 0); if (VAR_1 < 0)
return VAR_1; pb = mkv->info_bc; put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); if ((tag = av_dict_get(VAR_0->metadata, "title", NULL, 0)))
put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value); if (!(VAR_0->flags & AVFMT_FLAG_BITEXACT)) { put_ebml_string(pb, MATROSKA_ID_MUXINGAPP, LIBAVFORMAT_IDENT); if ((tag = av_dict_get(VAR_0->metadata, "encoding_tool", NULL, 0)))
put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, tag->value); else
put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT); if (mkv->mode != MODE_WEBM) { uint32_t segment_uid[4]; AVLFG lfg; av_lfg_init(&lfg, av_get_random_seed()); for (VAR_2 = 0; VAR_2 < 4; VAR_2++) segment_uid[VAR_2] = av_lfg_get(&lfg); put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16); } } else { const char *VAR_4 = "Lavf"; put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , VAR_4); put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, VAR_4); } if (ff_parse_creation_time_metadata(VAR_0, &creation_time, 0) > 0) { int64_t date_utc = (creation_time - 978307200000000LL) * 1000; uint8_t date_utc_buf[8]; AV_WB64(date_utc_buf, date_utc); put_ebml_binary(pb, MATROSKA_ID_DATEUTC, date_utc_buf, 8); } mkv->duration = 0; mkv->duration_offset = avio_tell(pb); if (!mkv->is_live) { int64_t metadata_duration = get_metadata_duration(VAR_0); if (VAR_0->duration > 0) { int64_t scaledDuration = av_rescale(VAR_0->duration, 1000, AV_TIME_BASE); put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration); av_log(VAR_0, AV_LOG_DEBUG, "Write early duration from recording time = %" PRIu64 "\n", scaledDuration); } else if (metadata_duration > 0) { int64_t scaledDuration = av_rescale(metadata_duration, 1000, AV_TIME_BASE); put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration); av_log(VAR_0, AV_LOG_DEBUG, "Write early duration from metadata = %" PRIu64 "\n", scaledDuration); } else { put_ebml_void(pb, 11); } } if ((VAR_0->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)
end_ebml_master_crc32_preliminary(VAR_0->pb, &mkv->info_bc, mkv, mkv->info); else
end_ebml_master_crc32(VAR_0->pb, &mkv->info_bc, mkv, mkv->info); pb = VAR_0->pb; mkv->stream_durations = av_mallocz(VAR_0->nb_streams * sizeof(int64_t)); mkv->stream_duration_offsets = av_mallocz(VAR_0->nb_streams * sizeof(int64_t)); VAR_1 = mkv_write_tracks(VAR_0); if (VAR_1 < 0)
goto fail; for (VAR_2 = 0; VAR_2 < VAR_0->nb_chapters; VAR_2++) mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - VAR_0->chapters[VAR_2]->id); VAR_1 = mkv_write_chapters(VAR_0); if (VAR_1 < 0)
goto fail; if (mkv->mode != MODE_WEBM) { VAR_1 = mkv_write_attachments(VAR_0); if (VAR_1 < 0)
goto fail; } VAR_1 = mkv_write_tags(VAR_0); if (VAR_1 < 0)
goto fail; if (!(VAR_0->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)
mkv_write_seekhead(pb, mkv); mkv->cues = mkv_start_cues(mkv->segment_offset); if (!mkv->cues) { VAR_1 = AVERROR(ENOMEM); goto fail; } if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && mkv->reserve_cues_space) { mkv->cues_pos = avio_tell(pb); put_ebml_void(pb, mkv->reserve_cues_space); } av_init_packet(&mkv->cur_audio_pkt); mkv->cur_audio_pkt.size = 0; mkv->cluster_pos = -1; avio_flush(pb); if (pb->seekable & AVIO_SEEKABLE_NORMAL) { if (mkv->cluster_time_limit < 0)
mkv->cluster_time_limit = 5000; if (mkv->cluster_size_limit < 0)
mkv->cluster_size_limit = 5 * 1024 * 1024; } else { if (mkv->cluster_time_limit < 0)
mkv->cluster_time_limit = 1000; if (mkv->cluster_size_limit < 0)
mkv->cluster_size_limit = 32 * 1024; } return 0; fail:
mkv_free(mkv); return VAR_1; }