Ticket #8578: 0001-avformat-matroskaenc-Write-level-1-elements-in-one-g.patch

File 0001-avformat-matroskaenc-Write-level-1-elements-in-one-g.patch, 11.5 KB (added by mkver, 7 years ago)

Patch to write level 1 elements in one go again for release 4.2

  • libavformat/matroskaenc.c

    From 8b9edb10cac98c618f5d491861dbe6cb7e90caaa Mon Sep 17 00:00:00 2001
    From: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
    Date: Mon, 23 Mar 2020 02:38:11 +0100
    Subject: [PATCH] avformat/matroskaenc: Write level 1 elements in one go
    
    Up until now, writing level 1 elements proceeded as follows: First, the
    element id was written to the ordinary output AVIOContext and a dynamic
    buffer was opened for the content of the level 1 element in
    start_ebml_master_crc32(). Then this buffer was actually used and after it
    was closed (in end_ebml_master_crc32()), the size field corresponding to
    the buffer's size was written, after which the actual data was written.
    
    This commit changes this: Nothing is written to the main AVIOContext any
    more in start_ebml_master_crc32(). end_ebml_master_crc32() now writes
    both the id, the length field as well as the data. This is benefical for
    streaming, because a client that receives just a Cluster ID and nothing
    more might infer that this is EOF; in certain usecases there is also the
    danger of a client receiving the Cluster without the actual Cluster ID
    at the beginning.
    
    Addresses #8578.
    
    Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
    ---
     libavformat/matroskaenc.c | 65 ++++++++++++++++++++++-----------------
     1 file changed, 36 insertions(+), 29 deletions(-)
    
    diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
    index cef504fa05..2014d73845 100644
    a b static void end_ebml_master(AVIOContext *pb, ebml_master master)  
    331331    avio_seek(pb, pos, SEEK_SET);
    332332}
    333333
    334 static int start_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv,
    335                                    uint32_t elementid)
     334static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv)
    336335{
    337336    int ret;
    338337
    339338    if ((ret = avio_open_dyn_buf(dyn_cp)) < 0)
    340339        return ret;
    341340
    342     put_ebml_id(pb, elementid);
    343341    if (mkv->write_crc)
    344342        put_ebml_void(*dyn_cp, 6); /* Reserve space for CRC32 so position/size calculations using avio_tell() take it into account */
    345343
    346344    return 0;
    347345}
    348346
    349 static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv)
     347static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp,
     348                                  MatroskaMuxContext *mkv, uint32_t id)
    350349{
    351350    uint8_t *buf, crc[4];
    352351    int size, skip = 0;
    353352
     353    put_ebml_id(pb, id);
    354354    size = avio_close_dyn_buf(*dyn_cp, &buf);
    355355    put_ebml_num(pb, size, 0);
    356356    if (mkv->write_crc) {
    … … static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, Matrosk  
    368368* Complete ebml master without destroying the buffer, allowing for later updates
    369369*/
    370370static void end_ebml_master_crc32_preliminary(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv,
    371                                               int64_t *pos)
     371                                              uint32_t id, int64_t *pos)
    372372{
    373373    uint8_t *buf;
    374374    int size = avio_get_dyn_buf(*dyn_cp, &buf);
    375375
    376376    *pos = avio_tell(pb);
    377377
     378    put_ebml_id(pb, id);
    378379    put_ebml_num(pb, size, 0);
    379380    avio_write(pb, buf, size);
    380381}
    … … static int64_t mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv)  
    500501        }
    501502    }
    502503
    503     if (start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD) < 0) {
     504    if (start_ebml_master_crc32(&dyn_cp, mkv) < 0) {
    504505        currentpos = -1;
    505506        goto fail;
    506507    }
    … … static int64_t mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv)  
    517518        put_ebml_uint(dyn_cp, MATROSKA_ID_SEEKPOSITION, entry->segmentpos);
    518519        end_ebml_master(dyn_cp, seekentry);
    519520    }
    520     end_ebml_master_crc32(pb, &dyn_cp, mkv);
     521    end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD);
    521522
    522523    if (seekhead->reserved_size > 0) {
    523524        uint64_t remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb);
    … … static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tra  
    574575    int i, j, ret;
    575576
    576577    currentpos = avio_tell(pb);
    577     ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CUES);
     578    ret = start_ebml_master_crc32(&dyn_cp, mkv);
    578579    if (ret < 0)
    579580        return ret;
    580581
    … … static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tra  
    620621        i += j - 1;
    621622        end_ebml_master(dyn_cp, cuepoint);
    622623    }
    623     end_ebml_master_crc32(pb, &dyn_cp, mkv);
     624    end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CUES);
    624625
    625626    return currentpos;
    626627}
    … … static int mkv_write_tracks(AVFormatContext *s)  
    14501451    if (ret < 0)
    14511452        return ret;
    14521453
    1453     ret = start_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, MATROSKA_ID_TRACKS);
     1454    ret = start_ebml_master_crc32(&mkv->tracks_bc, mkv);
    14541455    if (ret < 0)
    14551456        return ret;
    14561457
    … … static int mkv_write_tracks(AVFormatContext *s)  
    14651466    }
    14661467
    14671468    if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)
    1468         end_ebml_master_crc32_preliminary(pb, &mkv->tracks_bc, mkv, &mkv->tracks_pos);
     1469        end_ebml_master_crc32_preliminary(pb, &mkv->tracks_bc, mkv,
     1470                                          MATROSKA_ID_TRACKS, &mkv->tracks_pos);
    14691471    else
    1470         end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv);
     1472        end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, MATROSKA_ID_TRACKS);
    14711473
    14721474    return 0;
    14731475}
    … … static int mkv_write_chapters(AVFormatContext *s)  
    14861488    ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_CHAPTERS, avio_tell(pb));
    14871489    if (ret < 0) return ret;
    14881490
    1489     ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS);
     1491    ret = start_ebml_master_crc32(&dyn_cp, mkv);
    14901492    if (ret < 0) return ret;
    14911493
    14921494    editionentry = start_ebml_master(dyn_cp, MATROSKA_ID_EDITIONENTRY, 0);
    … … static int mkv_write_chapters(AVFormatContext *s)  
    15241526        end_ebml_master(dyn_cp, chapteratom);
    15251527    }
    15261528    end_ebml_master(dyn_cp, editionentry);
    1527     end_ebml_master_crc32(pb, &dyn_cp, mkv);
     1529    end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS);
    15281530
    15291531    mkv->wrote_chapters = 1;
    15301532    return 0;
    … … static int mkv_write_tag_targets(AVFormatContext *s, uint32_t elementid,  
    15761578        ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_TAGS, avio_tell(s->pb));
    15771579        if (ret < 0) return ret;
    15781580
    1579         start_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv, MATROSKA_ID_TAGS);
     1581        start_ebml_master_crc32(&mkv->tags_bc, mkv);
     1582        if (ret < 0)
     1583            return ret;
    15801584    }
    15811585    pb = mkv->tags_bc;
    15821586
    … … static int mkv_write_tags(AVFormatContext *s)  
    17161720
    17171721    if (mkv->tags_bc) {
    17181722        if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)
    1719             end_ebml_master_crc32_preliminary(s->pb, &mkv->tags_bc, mkv, &mkv->tags_pos);
     1723            end_ebml_master_crc32_preliminary(s->pb, &mkv->tags_bc, mkv,
     1724                                              MATROSKA_ID_TAGS, &mkv->tags_pos);
    17201725        else
    1721             end_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv);
     1726            end_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv, MATROSKA_ID_TAGS);
    17221727    }
    17231728    return 0;
    17241729}
    … … static int mkv_write_attachments(AVFormatContext *s)  
    17421747    ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_ATTACHMENTS, avio_tell(pb));
    17431748    if (ret < 0) return ret;
    17441749
    1745     ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS);
     1750    ret = start_ebml_master_crc32(&dyn_cp, mkv);
    17461751    if (ret < 0) return ret;
    17471752
    17481753    for (i = 0; i < s->nb_streams; i++) {
    … … static int mkv_write_attachments(AVFormatContext *s)  
    18151820        mkv->attachments->entries[mkv->attachments->num_entries].stream_idx = i;
    18161821        mkv->attachments->entries[mkv->attachments->num_entries++].fileuid  = fileuid;
    18171822    }
    1818     end_ebml_master_crc32(pb, &dyn_cp, mkv);
     1823    end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS);
    18191824
    18201825    return 0;
    18211826}
    … … static int mkv_write_header(AVFormatContext *s)  
    19011906    ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_INFO, avio_tell(pb));
    19021907    if (ret < 0) goto fail;
    19031908
    1904     ret = start_ebml_master_crc32(pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO);
     1909    ret = start_ebml_master_crc32(&mkv->info_bc, mkv);
    19051910    if (ret < 0)
    19061911        return ret;
    19071912    pb = mkv->info_bc;
    … … static int mkv_write_header(AVFormatContext *s)  
    19601965        }
    19611966    }
    19621967    if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live)
    1963         end_ebml_master_crc32_preliminary(s->pb, &mkv->info_bc, mkv, &mkv->info_pos);
     1968        end_ebml_master_crc32_preliminary(s->pb, &mkv->info_bc, mkv,
     1969                                          MATROSKA_ID_INFO, &mkv->info_pos);
    19641970    else
    1965         end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv);
     1971        end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO);
    19661972    pb = s->pb;
    19671973
    19681974    // initialize stream_duration fields
    … … static void mkv_start_new_cluster(AVFormatContext *s, AVPacket *pkt)  
    22582264{
    22592265    MatroskaMuxContext *mkv = s->priv_data;
    22602266
    2261     end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv);
     2267    end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER);
    22622268    mkv->cluster_pos = -1;
    22632269    av_log(s, AV_LOG_DEBUG,
    22642270           "Starting new cluster at offset %" PRIu64 " bytes, "
    … … static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_  
    24032409
    24042410    if (mkv->cluster_pos == -1) {
    24052411        mkv->cluster_pos = avio_tell(s->pb);
    2406         ret = start_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER);
     2412        ret = start_ebml_master_crc32(&mkv->cluster_bc, mkv);
    24072413        if (ret < 0)
    24082414            return ret;
    24092415        put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts));
    … … static int mkv_write_flush_packet(AVFormatContext *s, AVPacket *pkt)  
    25392545
    25402546    if (!pkt) {
    25412547        if (mkv->cluster_pos != -1) {
    2542             end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv);
     2548            end_ebml_master_crc32(s->pb, &mkv->cluster_bc,
     2549                                  mkv, MATROSKA_ID_CLUSTER);
    25432550            mkv->cluster_pos = -1;
    25442551            av_log(s, AV_LOG_DEBUG,
    25452552                   "Flushing cluster at offset %" PRIu64 " bytes\n",
    … … static int mkv_write_trailer(AVFormatContext *s)  
    25702577    }
    25712578
    25722579    if (mkv->cluster_bc) {
    2573         end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv);
     2580        end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER);
    25742581    }
    25752582
    25762583    ret = mkv_write_chapters(s);
    … … static int mkv_write_trailer(AVFormatContext *s)  
    26192626        avio_seek(mkv->info_bc, mkv->duration_offset, SEEK_SET);
    26202627        put_ebml_float(mkv->info_bc, MATROSKA_ID_DURATION, mkv->duration);
    26212628        avio_seek(pb, mkv->info_pos, SEEK_SET);
    2622         end_ebml_master_crc32(pb, &mkv->info_bc, mkv);
     2629        end_ebml_master_crc32(pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO);
    26232630
    26242631        // write tracks master
    26252632        avio_seek(pb, mkv->tracks_pos, SEEK_SET);
    2626         end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv);
     2633        end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, MATROSKA_ID_TRACKS);
    26272634
    26282635        // update stream durations
    26292636        if (!mkv->is_live && mkv->stream_durations) {
    … … static int mkv_write_trailer(AVFormatContext *s)  
    26522659        }
    26532660        if (mkv->tags_bc && !mkv->is_live) {
    26542661            avio_seek(pb, mkv->tags_pos, SEEK_SET);
    2655             end_ebml_master_crc32(pb, &mkv->tags_bc, mkv);
     2662            end_ebml_master_crc32(pb, &mkv->tags_bc, mkv, MATROSKA_ID_TAGS);
    26562663        }
    26572664
    26582665        avio_seek(pb, currentpos, SEEK_SET);