From patchwork Sun Jan 16 23:04:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 33633 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:cd86:0:0:0:0:0 with SMTP id d128csp2274168iog; Sun, 16 Jan 2022 15:07:36 -0800 (PST) X-Google-Smtp-Source: ABdhPJx3xVSfxs5cfzi1SQnqv2slknTNBxNFmdR2t916HnXaTs+ooDadKe+v06v8BgacGZfRN/1s X-Received: by 2002:a05:6402:f16:: with SMTP id i22mr17955129eda.165.1642374456019; Sun, 16 Jan 2022 15:07:36 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id w6si6807866edc.624.2022.01.16.15.07.35; Sun, 16 Jan 2022 15:07:36 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@outlook.com header.s=selector1 header.b=XUsKGwor; arc=fail (body hash mismatch); spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=outlook.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 91DA368AFD1; Mon, 17 Jan 2022 01:05:37 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-oln040092074045.outbound.protection.outlook.com [40.92.74.45]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A853868AEC8 for ; Mon, 17 Jan 2022 01:05:35 +0200 (EET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=UK1krH4j3+Mqq8yioTiQ3axjxF6DU+E9Cnc9c/rtVWhKZxra8IcsoP29NOwLrlrxtKSU4RPw1QFzlAawpNDSor4736meStv0QmYWpi47QBTtc/NmmO+MeM/PrhTKFW/VjJ3gM60X25Gk1mKrVJuVASkGSzneNovIARL0UVITMmWUCS9tvm0C12IQMKFrN+oh1LAtyOspYzvi6TleFf0oJfNi/Fn7dS1pmIZTpml2L1wk9NNX2j41dQJBGufxEo3sTcDqxfTpyCk4dK8GB3kmI9ZGmqAWMHSBESKkg2VfWK579rTLmPMjfgJwX8ctS+IvmodB8uDV5sh0shtkeQ9O3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=0n0A6GStp6/oqYHXALkVZ8DDNdvOjYcJHDFysqcifJs=; b=RcQPQMTWjG4PUWA/fcRPW33CcmtcSx+qAfdZNkKjy23SShR2W5mEXxg1Sc413YwXZ16gTLBRuyUFb2XrXKnYPaOMhKZp4B/F3WFE22qPqvWbyed91a/Av70B2ir+9YpZbR0txyvP9ka/TlYfX+RYiD2bIuFwjk83cXSoO6xl0EGJwl3eS20hHkcisQnKN0CyE6j9JAxgbb7bLlp307vzBNYsXdKR2YMd2JOqugRvTHSraMvL+acKIphKFA8fHTcSRLePmiiz/QpUSXsfkpT2lrAyHZ6YlBFhN7Yod6A+HMsY/Mwqxq6eFYsVKhO2Dw8N/sl6JCmNc67OSU7KY+ZwoQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0n0A6GStp6/oqYHXALkVZ8DDNdvOjYcJHDFysqcifJs=; b=XUsKGworBzSz4S9DHI3xy/g2luUfk/TbCA8YzT9mGwG7PuEUMl/pyQMq1ptZHp/9BXRzpzeVQa6uCn70OcTmhSC855WO07bzymenqgcwdbw2McJr0CcvNX4W6D6Jmt6COpBlkxRcNbIeckSW/m50vDrs24YVAlA7m4ARZP4LML3ODaJxgBH8aaKGxbxxXi2N5yya2hPyAzjGD4YrF5wO1lxWE8ke0Sv7pQS4fhGTH6uAg92zgttlccLDkDGtqziJiHeu5lmMWv4U7FQm97aKeo/FxXNFcHW+zW+ZxIPpCvvjEIgbDLQ/fzD23N9nCa+EoHWczaRG/11kxeO+OSrMdw== Received: from AM7PR03MB6660.eurprd03.prod.outlook.com (2603:10a6:20b:1c1::22) by VI1PR0301MB2560.eurprd03.prod.outlook.com (2603:10a6:800:68::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4888.11; Sun, 16 Jan 2022 23:05:30 +0000 Received: from AM7PR03MB6660.eurprd03.prod.outlook.com ([fe80::19fc:be9f:2c9c:53f5]) by AM7PR03MB6660.eurprd03.prod.outlook.com ([fe80::19fc:be9f:2c9c:53f5%9]) with mapi id 15.20.4888.013; Sun, 16 Jan 2022 23:05:30 +0000 From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Mon, 17 Jan 2022 00:04:01 +0100 Message-ID: X-Mailer: git-send-email 2.32.0 In-Reply-To: References: X-TMN: [apEPjoPsZUg0SfT6nAQJOsVJZpeDLKiX] X-ClientProxiedBy: AM0PR10CA0070.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:208:15::23) To AM7PR03MB6660.eurprd03.prod.outlook.com (2603:10a6:20b:1c1::22) X-Microsoft-Original-Message-ID: <20220116230405.194506-20-andreas.rheinhardt@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: d916ddb8-6fad-42e7-5150-08d9d944b13a X-MS-Exchange-SLBlob-MailProps: +LiGfBxqLEuZvKHt/RRJ4O3wxWCrUcc4nfNgvZzzzWJSNaK3vnCJ+Imsa2HWJUXCymt2f/yTUBZ+hIY3Vo+p2nk5EDEXkp/O193HbRq9AtyzHyEfPig1ELmWL2lsYL3uShL5FBHcrxRq0+Uv+oJyhk6K6ZV6Qqi3y4EMNHdxiK1Jx7mcUv0hyLavOfEZCqyOuTVaq0VRZ1cmQaiLc4WOSRdCx+zb24WLUR10dFyxnm7Q6WYj3LREK167iV9NsiUk5QAuXc1L9VILVkQ9XQjQZ/C6XaeClB5HpCAYKr/LwbEgMF5/0zXaoJOAB7zP5JY1dGJtHKi21aFaYzgZSzjT5AT+o3+K+/gZlu34yZXajV53x9NbBjnQLrp9sjCqtWE09v+QChEyYxWMt6ZQffmeF3ta9YJLsJEJURqLw6kd7GISS3n5kQ7KjXfxvdUNeLkF/XE1r0YcgMPl/BaY+DVsHbwB2HZ7l6BTdFSk1oZwJPmlo/sp0ltJjNqCvcN8WtLI222UG2/pO742SPVj1iwhEBSrZ78Km8u6T7x/eBRBHjCwnnOJFBxm8V1q6WrRcZr60mU0yCPCDQNzFTzaa9f8uY1JBAtrn1Zcu34RJpLu1cM8k3ppPVCzcDZuad38QmFjTqeTAeceiAY0VQxbBrH5yTa+WVIh0b8/0h2t2Ap15rtwh5ciEX7AZnq08DAYwBbg/UyF/HadEFxbVdqciIE5JfTuimAECnrk1dxBZkDrkmNDiFEtDlh3a8Sb30Yly+pRWakYPSEYA9p6MQm9nyqB5VQLRqnF58q+ X-MS-TrafficTypeDiagnostic: VI1PR0301MB2560:EE_ X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: rdO8Z8EpO19gBm6PfSUFZ9g0Fn8WeB5hvAr6uBjgSC3wbdvsopATctGen1xaRuaP1lpnsGv7knxM5+ii/df2bEdCxH7Nr7psspta7nIgtomECPeVw9FAdfnZ3RDYF1tDzPAOEZqMQNBd9rGBdnq53vXsMT4qSa9d5TuHOQJzQGgRPWCEbFrFwKXWsNBwJXMKxX1xdowa7lNKghtCUMUZJCQWtB/lBFByqgd2ViggaGGvn98EqmnfYfTQMkZNVNHFtO+B9i1p84DD/YFcvL/ZB04GTMMFLOwct+6z3wAEIlduDRWEOatgl0qOu931eiwxpYh9NExTUzxn54a940HfoggYUg3L32p31GkjXsoY+uB9fYOYdsPFU7rI6/AUUAmadRSGYRAbZX1tyWsnWaMe2XK2QAPIn2I4wFmtqAYwDIdryjnRHLWb7yz8Pw9TWj68QFrELqcNw2VYdiNBrDQ2Ol8Mg10Boe0v0QeNmRwZiQkWtsAVuGrCfFHrIqlbB6M73kXSRf/MclxQRSIsnC3dyoZSyaVw+GuEKWihXNkncjKDdYS7fkQlnN4tbA+MYKKVGWYGRnhGbk0ZNQdOa1OaGA== X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: KUMfP81RoIL4R5868YMYRf5AOkxKtAqt+81AMvOIrjMHFL1QMjI8kzaHwx2KyRkpbIKyK27z8cFb/d1EExBbkNTTKEGHtm4lDhNgS6JeHgXV0UdnKdwfeDPNujqj/ALdw11AsDsK1WVsS7NThfvgaspjBcAgeu3PFNmI916VyBu614Ex9cKi8Gz6cMN+7Fy/dewx6JkVEbHKy2nkxxoFrEKjO475rk2uREWYKDhzR5l90Mw86XMO44ezpFoz6PPU8c7g7uJFTqmHoFniEf/NUFQBxg5Cw8jADGGgeS3CGmW7LA5Y/cCfJy+2F4qI4XtnB9CPX1p6TVs3/m81TcsVGgu8JUwzlIzsFM3JyOGtZwmeE9DN+DPb9yc/NuZByhZ0oLDjsa7NFMXxMbjwS/9MlmS5BXd8ec5ioM1q8gerbC2AKHeL/XQk335v/PU1Nyft4RNCNKRdjROLAY9OsKBWwMdod+4rexcqbSxUnQzWjKae/wn6SUqWXTW6wogBMJLA+2jt9m4p6z/yh4N9Z3aC+v6IuFbOiMI+thc2Er3aVR5rWcNbbhDoewz1ViYlHnA6uWShzyPA99Jc4nqvUv8ExSEn1H0dlBaTXupsbVcnSlTvzJrNkxh8f6y2BPziRjAeBywra5vWdVOyNPMG4vIsqznK+XcH+wAsJQkKiclBgjyKerDGg9U1VPiDxYB7qVMiWtO+7mO3WaSrj7PSHNsfTfQr2qgxaGHkp53AybRgeAunOvJUq55PwJy9iHW4ji8LrYZnuKSU+Lotx+s+mqTvpuOAg/NMxtxIODOAhjYy/tdvMV+qfU53CssQzbdinTJNB1akkjVJemM9jFqdSnN+VCV2aYu9LEelMVTbSTpbTptyAWFHJJXU4sZVWo+1MNyVU5+fh0Qv7SGkmNfPJCR0NwdIjsaFUC2pajsut3B7VkuR28fiQKqgzWuGL7MRUrVoHTbPiks6lnTg04kjB5ApaQ== X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: d916ddb8-6fad-42e7-5150-08d9d944b13a X-MS-Exchange-CrossTenant-AuthSource: AM7PR03MB6660.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Jan 2022 23:05:30.5903 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0301MB2560 Subject: [FFmpeg-devel] [PATCH 21/25] avformat/matroskaenc: Don't waste bytes on BlockGroup length fields X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: y7TWhf+wpNdS This commit uses the new EbmlWriter API to write the length fields of the BlockGroup and its descendants that are themselves Master elements (namely BlockAdditions and BlockMore) on the least amount of bytes. This fixes regressions introduced when the special code for writing general subtitles was removed. Accordingly, the binsub-mksenc and matroska-zero-length-block FATE-tests have now been reverted back to their old state again; the advantages of this approach are evident with the matroska-vp8-alpha-remux test which up until now wrote all the length fields of all BlockGroups, BlockAdditions and BlockMore on eight bytes. Using the EbmlWriter API also allowed to improve locality in mkv_write_block(): E.g. both DiscardPadding as well as the BlockAdditional side-data are now directly used to add elements to the writer whereas the earlier code had to first check for whether a BlockGroup should be used and then check again (after the place where a BlockGroup would be opened if one were used) for whether there is DiscardPadding or BlockAdditional side-data to write. Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 208 +++++++++++++--------- tests/ref/fate/binsub-mksenc | 2 +- tests/ref/fate/matroska-vp8-alpha-remux | 4 +- tests/ref/fate/matroska-zero-length-block | 4 +- tests/ref/fate/webm-dash-chapters | 4 +- 5 files changed, 130 insertions(+), 92 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index fdce3fad49..a3c84eb63b 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -99,9 +99,18 @@ typedef enum EbmlType { EBML_STR, EBML_UTF8 = EBML_STR, EBML_BIN, + EBML_BLOCK, ///< pseudo-type for writing BlockGroups/SimpleBlocks EBML_MASTER, } EbmlType; +typedef struct BlockContext { + struct mkv_track *track; + const AVPacket *pkt; + int16_t rel_ts; + uint8_t flags; + NALUList h2645_nalu_list; +} BlockContext; + typedef struct EbmlMaster { int nb_elements; ///< -1 if not finished int containing_master; ///< -1 if no parent exists @@ -118,6 +127,7 @@ typedef struct EbmlElement { double f; const char *str; const uint8_t *bin; + struct MatroskaMuxContext *mkv; ///< used by EBML_BLOCK EbmlMaster master; } priv; } EbmlElement; @@ -185,6 +195,8 @@ typedef struct mkv_track { typedef struct MatroskaMuxContext { const AVClass *class; + AVFormatContext *ctx; + int mode; ebml_stored_master info; ebml_stored_master track; @@ -200,7 +212,7 @@ typedef struct MatroskaMuxContext { mkv_cues cues; int64_t cues_pos; - NALUList h2645_nalu_list; + BlockContext cur_block; AVPacket *cur_audio_pkt; @@ -339,20 +351,6 @@ static void put_ebml_uint(AVIOContext *pb, uint32_t elementid, uint64_t val) avio_w8(pb, (uint8_t)(val >> i * 8)); } -static void put_ebml_sint(AVIOContext *pb, uint32_t elementid, int64_t val) -{ - int i, bytes = 1; - uint64_t tmp = 2 * (uint64_t)(val < 0 ? val^-1 : val); - - while (tmp >>= 8) - bytes++; - - put_ebml_id(pb, elementid); - put_ebml_length(pb, bytes, 0); - for (i = bytes - 1; i >= 0; i--) - avio_w8(pb, (uint8_t)(val >> i * 8)); -} - static void put_ebml_float(AVIOContext *pb, uint32_t elementid, double val) { put_ebml_id(pb, elementid); @@ -500,6 +498,19 @@ static void ebml_writer_add_uint(EbmlWriter *writer, uint32_t id, elem->priv.uint = val; } +static void ebml_writer_add_sint(EbmlWriter *writer, uint32_t id, + int64_t val) +{ + EbmlElement *elem = ebml_writer_add(writer, id, EBML_SINT); + elem->priv.sint = val; +} + +static void ebml_writer_add_block(EbmlWriter *writer, MatroskaMuxContext *mkv) +{ + EbmlElement *elem = ebml_writer_add(writer, MATROSKA_ID_BLOCK, EBML_BLOCK); + elem->priv.mkv = mkv; +} + static int ebml_writer_str_len(EbmlElement *elem) { size_t len = strlen(elem->priv.str); @@ -566,6 +577,52 @@ static int ebml_writer_master_len(EbmlWriter *writer, EbmlElement *elem, return master->priv.master.nb_elements; } +static int ebml_writer_block_len(EbmlElement *elem) +{ + MatroskaMuxContext *const mkv = elem->priv.mkv; + BlockContext *const block = &mkv->cur_block; + mkv_track *const track = block->track; + const AVPacket *const pkt = block->pkt; + int err, size; + + if (track->reformat) { + err = track->reformat(mkv, NULL, pkt, &size); + if (err < 0) { + av_log(mkv->ctx, AV_LOG_ERROR, "Error when reformatting data of " + "a packet from stream %d.\n", pkt->stream_index); + return err; + } + } else { + size = pkt->size; + if (track->offset <= size) + size -= track->offset; + } + elem->size = track->track_num_size + 3U + size; + + return 0; +} + +static void ebml_writer_write_block(const EbmlElement *elem, AVIOContext *pb) +{ + MatroskaMuxContext *const mkv = elem->priv.mkv; + BlockContext *const block = &mkv->cur_block; + mkv_track *const track = block->track; + const AVPacket *const pkt = block->pkt; + + put_ebml_num(pb, track->track_num, track->track_num_size); + avio_wb16(pb, block->rel_ts); + avio_w8(pb, block->flags); + + if (track->reformat) { + int size; + track->reformat(mkv, pb, pkt, &size); + } else { + const uint8_t *data = pkt->data; + unsigned offset = track->offset <= pkt->size ? track->offset : 0; + avio_write(pb, data + offset, pkt->size - offset); + } +} + static int ebml_writer_elem_len(EbmlWriter *writer, EbmlElement *elem, int remaining_elems) { @@ -585,6 +642,9 @@ static int ebml_writer_elem_len(EbmlWriter *writer, EbmlElement *elem, case EBML_SINT: ret = ebml_writer_sint_len(elem); break; + case EBML_BLOCK: + ret = ebml_writer_block_len(elem); + break; case EBML_MASTER: ret = ebml_writer_master_len(writer, elem, remaining_elems); break; @@ -624,6 +684,9 @@ static int ebml_writer_elem_write(const EbmlElement *elem, AVIOContext *pb) avio_write(pb, data, elem->size); break; } + case EBML_BLOCK: + ebml_writer_write_block(elem, pb); + break; case EBML_MASTER: { int nb_elems = elem->priv.master.nb_elements; @@ -749,7 +812,7 @@ static void mkv_deinit(AVFormatContext *s) ffio_free_dyn_buf(&mkv->track.bc); ffio_free_dyn_buf(&mkv->tags.bc); - av_freep(&mkv->h2645_nalu_list.nalus); + av_freep(&mkv->cur_block.h2645_nalu_list.nalus); av_freep(&mkv->cues.entries); av_freep(&mkv->tracks); } @@ -2356,9 +2419,9 @@ static int mkv_reformat_h2645(MatroskaMuxContext *mkv, AVIOContext *pb, { int ret; if (pb) { - ff_nal_units_write_list(&mkv->h2645_nalu_list, pb, pkt->data); + ff_nal_units_write_list(&mkv->cur_block.h2645_nalu_list, pb, pkt->data); } else { - ret = ff_nal_units_create_list(&mkv->h2645_nalu_list, pkt->data, pkt->size); + ret = ff_nal_units_create_list(&mkv->cur_block.h2645_nalu_list, pkt->data, pkt->size); if (ret < 0) return ret; *size = ret; @@ -2423,14 +2486,25 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, mkv_track *track, const AVPacket *pkt, int keyframe, int64_t ts, uint64_t duration) { - uint8_t *data = NULL, *side_data = NULL; + uint8_t *side_data; size_t side_data_size; - int err = 0, offset = 0, size = pkt->size; uint64_t additional_id; - uint32_t blockid = MATROSKA_ID_SIMPLEBLOCK; int64_t discard_padding = 0; unsigned track_number = track->track_num; - ebml_master block_group, block_additions, block_more; + EBML_WRITER(9); + + mkv->cur_block.track = track; + mkv->cur_block.pkt = pkt; + mkv->cur_block.rel_ts = ts - mkv->cluster_pts; + mkv->cur_block.flags = 0; + + /* Open a BlockGroup with a Block now; it will later be converted + * to a SimpleBlock if possible. */ + ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKGROUP); + ebml_writer_add_block(&writer, mkv); + + if (duration) + ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKDURATION, duration); /* The following string is identical to the one in mkv_write_vtt_blocks * so that only one copy needs to exist in binaries. */ @@ -2441,22 +2515,6 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, pkt->size, pkt->pts, pkt->dts, pkt->duration, avio_tell(pb), mkv->cluster_pos, track_number, keyframe != 0); - if (track->reformat) { - err = track->reformat(mkv, NULL, pkt, &size); - } else - data = pkt->data; - - if (err < 0) { - av_log(logctx, AV_LOG_ERROR, "Error when reformatting data of " - "a packet from stream %d.\n", pkt->stream_index); - return err; - } - - if (track->offset <= size) { - size -= track->offset; - offset = track->offset; - } - side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_data_size); @@ -2464,62 +2522,39 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, discard_padding = av_rescale_q(AV_RL32(side_data + 4), (AVRational){1, par->sample_rate}, (AVRational){1, 1000000000}); + ebml_writer_add_sint(&writer, MATROSKA_ID_DISCARDPADDING, discard_padding); } side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); - if (side_data) { + if (side_data && side_data_size >= 8 && // Only the Codec-specific BlockMore (id == 1) is currently supported. - if (side_data_size < 8 || (additional_id = AV_RB64(side_data)) != 1) { - side_data_size = 0; - } else { - side_data += 8; - side_data_size -= 8; - } - } - - if (side_data_size || discard_padding || duration) { - block_group = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, 0); - blockid = MATROSKA_ID_BLOCK; - } - - put_ebml_id(pb, blockid); - put_ebml_length(pb, size + track->track_num_size + 3, 0); - put_ebml_num(pb, track_number, track->track_num_size); - avio_wb16(pb, ts - mkv->cluster_pts); - avio_w8(pb, (blockid == MATROSKA_ID_SIMPLEBLOCK && keyframe) ? (1 << 7) : 0); - if (track->reformat) { - track->reformat(mkv, pb, pkt, &size); - } else { - avio_write(pb, data + offset, size); - } - - if (duration) - put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); - - if (blockid == MATROSKA_ID_BLOCK && !keyframe) - put_ebml_sint(pb, MATROSKA_ID_BLOCKREFERENCE, track->last_timestamp - ts); - track->last_timestamp = ts; - - if (discard_padding) - put_ebml_sint(pb, MATROSKA_ID_DISCARDPADDING, discard_padding); - - if (side_data_size) { - block_additions = start_ebml_master(pb, MATROSKA_ID_BLOCKADDITIONS, 0); - block_more = start_ebml_master(pb, MATROSKA_ID_BLOCKMORE, 0); + (additional_id = AV_RB64(side_data)) == 1) { + ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKADDITIONS); + ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKMORE); /* Until dbc50f8a our demuxer used a wrong default value * of BlockAddID, so we write it unconditionally. */ - put_ebml_uint (pb, MATROSKA_ID_BLOCKADDID, additional_id); - put_ebml_binary(pb, MATROSKA_ID_BLOCKADDITIONAL, - side_data, side_data_size); - end_ebml_master(pb, block_more); - end_ebml_master(pb, block_additions); - } - if (blockid == MATROSKA_ID_BLOCK) - end_ebml_master(pb, block_group); + ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKADDID, additional_id); + ebml_writer_add_bin (&writer, MATROSKA_ID_BLOCKADDITIONAL, + side_data + 8, side_data_size - 8); + ebml_writer_close_master(&writer); + ebml_writer_close_master(&writer); + } + + if (writer.nb_elements == 2) { + /* Nothing except the BlockGroup + Block. Can use a SimpleBlock. */ + writer.elements++; // Skip the BlockGroup. + writer.nb_elements--; + av_assert2(writer.elements[0].id == MATROSKA_ID_BLOCK); + writer.elements[0].id = MATROSKA_ID_SIMPLEBLOCK; + if (keyframe) + mkv->cur_block.flags |= 1 << 7; + } else if (!keyframe) + ebml_writer_add_sint(&writer, MATROSKA_ID_BLOCKREFERENCE, + track->last_timestamp - ts); - return 0; + return ebml_writer_write(&writer, pb); } static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, const AVPacket *pkt) @@ -2763,6 +2798,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) } } + track->last_timestamp = ts; mkv->duration = FFMAX(mkv->duration, ts + duration); track->duration = FFMAX(track->duration, ts + duration); @@ -3058,6 +3094,8 @@ static int mkv_init(struct AVFormatContext *s) unsigned nb_tracks = 0; int i; + mkv->ctx = s; + 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 || diff --git a/tests/ref/fate/binsub-mksenc b/tests/ref/fate/binsub-mksenc index 01e7db64f2..184661a3f0 100644 --- a/tests/ref/fate/binsub-mksenc +++ b/tests/ref/fate/binsub-mksenc @@ -1 +1 @@ -9dd2ff92a3da9fb50405db3d05e41042 +490b1b4beb4a614c06004609039ce779 diff --git a/tests/ref/fate/matroska-vp8-alpha-remux b/tests/ref/fate/matroska-vp8-alpha-remux index 413961672f..c17e8d0587 100644 --- a/tests/ref/fate/matroska-vp8-alpha-remux +++ b/tests/ref/fate/matroska-vp8-alpha-remux @@ -1,5 +1,5 @@ -89c4f6136f151f45c217ec363fe9db2b *tests/data/fate/matroska-vp8-alpha-remux.matroska -237178 tests/data/fate/matroska-vp8-alpha-remux.matroska +58147987d42f32d105d96b24b0755257 *tests/data/fate/matroska-vp8-alpha-remux.matroska +235018 tests/data/fate/matroska-vp8-alpha-remux.matroska #tb 0: 1/1000 #media_type 0: video #codec_id 0: vp8 diff --git a/tests/ref/fate/matroska-zero-length-block b/tests/ref/fate/matroska-zero-length-block index edee36a4ab..924cec1e3f 100644 --- a/tests/ref/fate/matroska-zero-length-block +++ b/tests/ref/fate/matroska-zero-length-block @@ -1,5 +1,5 @@ -c09d3b89ed0795817d671deb041fca1b *tests/data/fate/matroska-zero-length-block.matroska -650 tests/data/fate/matroska-zero-length-block.matroska +f37ba7e8a30eaa33c1fd0ef77447fb41 *tests/data/fate/matroska-zero-length-block.matroska +636 tests/data/fate/matroska-zero-length-block.matroska #tb 0: 1/1000 #media_type 0: subtitle #codec_id 0: subrip diff --git a/tests/ref/fate/webm-dash-chapters b/tests/ref/fate/webm-dash-chapters index 95114e6526..af8110ed1a 100644 --- a/tests/ref/fate/webm-dash-chapters +++ b/tests/ref/fate/webm-dash-chapters @@ -1,5 +1,5 @@ -01732642a0750de3959fd348092929a5 *tests/data/fate/webm-dash-chapters.webm -111162 tests/data/fate/webm-dash-chapters.webm +f97445ba73e182c888fa077348384083 *tests/data/fate/webm-dash-chapters.webm +111156 tests/data/fate/webm-dash-chapters.webm #extradata 0: 3469, 0xc6769ddc #tb 0: 1/1000 #media_type 0: audio