From patchwork Wed Mar 27 11:18:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Diego Felix de Souza via ffmpeg-devel X-Patchwork-Id: 12485 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 6D4A3448DC9 for ; Wed, 27 Mar 2019 13:21:28 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5697968A99F; Wed, 27 Mar 2019 13:21:28 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 45ADE68A98E for ; Wed, 27 Mar 2019 13:21:20 +0200 (EET) Received: by mail-wm1-f68.google.com with SMTP id h18so16348039wml.1 for ; Wed, 27 Mar 2019 04:21:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GUFiXQn4Fcr9dgOHA8N9QJBwfiF3pD4DQHJqCwZnLQ4=; b=mEMCeCaSbynXo7P5Gdl/R+t8p4zHGZnJD07y82zh2gLKeA5QIKV9G1Moy1idwsbSWC Un2jCe+p/LARoHr8k1n/eu4MF3cT0aACUxY6vZuTY36hRhKT9bG2qbsPCrD++NpbZY4K 3Ltf8l5WaH55hE+Fh8e63cvPgtOWxNj8UyIt6G2Wst9sRP14z0Mn6qgDSkCeU+wSXkXn xiqEIDpLobPx3pjdBbcivHP1hVVk9W9MpdTIqxIxIi0WwCes5wn1HEgX4L6pw+p1DxVF a9ylqehWVVqAx9torjvEahxb7hCsv7IQWf85/wAfyaegSUphuxcGXTO81d1/KIewO9C4 if9w== X-Gm-Message-State: APjAAAVKCMgzFz2KbGNAatmdDeHz7IOKP8lOvFIIf2srx5IF0lWN+Fd6 tzNbW2Ez16mWQ5E2YsljX/i1TVVC0YM= X-Google-Smtp-Source: APXvYqyoaVacQZGnquoMdbw94PMa3MHGG9pj1ABVVVwmELq8HFXbIRaMOKUCDFzmTCjG+BxENFmQDw== X-Received: by 2002:a1c:b455:: with SMTP id d82mr13153790wmf.153.1553685679537; Wed, 27 Mar 2019 04:21:19 -0700 (PDT) Received: from localhost.localdomain (ipbcc08c44.dynamic.kabel-deutschland.de. [188.192.140.68]) by smtp.googlemail.com with ESMTPSA id h10sm31745448wrs.27.2019.03.27.04.21.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Mar 2019 04:21:18 -0700 (PDT) To: ffmpeg-devel@ffmpeg.org Date: Wed, 27 Mar 2019 12:18:45 +0100 Message-Id: <20190327111852.3784-15-andreas.rheinhardt@googlemail.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20190327111852.3784-1-andreas.rheinhardt@googlemail.com> References: <20190308092604.3752-1-andreas.rheinhardt@googlemail.com> <20190327111852.3784-1-andreas.rheinhardt@googlemail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] =?utf-8?q?=5BPATCH_14/21=5D_avformat/matroskadec?= =?utf-8?q?=3A_Use_proper_levels_after_discont=C3=ADnuity?= X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andreas Rheinhardt via ffmpeg-devel From: Diego Felix de Souza via ffmpeg-devel Reply-To: FFmpeg development discussions and patches Cc: Andreas Rheinhardt , robux4@ycbcr.xyz Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" The earlier code set the level to zero upon seeking and after a discontinuity although in both cases parsing (re)starts at a level 1 element. Also set the segment's length to unkown if an error occured in order not to drop any valid data that happens to be beyond the designated end of the segment. Signed-off-by: Andreas Rheinhardt --- libavformat/matroskadec.c | 59 +++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 0179e5426e..42f1c21042 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -737,13 +737,24 @@ static const char *const matroska_doctypes[] = { "matroska", "webm" }; static int matroska_read_close(AVFormatContext *s); +static int matroska_reset_status(MatroskaDemuxContext *matroska, + uint32_t id, int64_t position) +{ + matroska->current_id = id; + matroska->num_levels = 1; + matroska->current_cluster.pos = 0; + + if (position >= 0) + return avio_seek(matroska->ctx->pb, position, SEEK_SET); + + return 0; +} + static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos) { AVIOContext *pb = matroska->ctx->pb; int64_t ret; uint32_t id; - matroska->current_id = 0; - matroska->num_levels = 0; /* seek to next position to resync from */ if ((ret = avio_seek(pb, last_pos + 1, SEEK_SET)) < 0) { @@ -759,7 +770,14 @@ static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos) id == MATROSKA_ID_CUES || id == MATROSKA_ID_TAGS || id == MATROSKA_ID_SEEKHEAD || id == MATROSKA_ID_ATTACHMENTS || id == MATROSKA_ID_CLUSTER || id == MATROSKA_ID_CHAPTERS) { - matroska->current_id = id; + /* Prepare the context for further parsing of a level 1 element. */ + matroska_reset_status(matroska, id, -1); + + /* Given that we are here means that an error has occured, + * so treat the segment as unknown length in order not to + * discard valid data that happens to be beyond the designated + * end of the segment. */ + matroska->levels[0].length = EBML_UNKNOWN_LENGTH; return 0; } id = (id << 8) | avio_r8(pb); @@ -1610,18 +1628,12 @@ static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska, matroska->current_id = 0; ret = ebml_parse(matroska, matroska_segment, matroska); - - /* remove dummy level */ - while (matroska->num_levels) { - uint64_t length = matroska->levels[--matroska->num_levels].length; - if (length == EBML_UNKNOWN_LENGTH) - break; - } } } - /* seek back */ - avio_seek(matroska->ctx->pb, before_pos, SEEK_SET); - matroska->current_id = saved_id; + + /* Seek back - notice that in all instances where this is used it is safe + * to set the level to 1 and unset the position of the current cluster. */ + matroska_reset_status(matroska, saved_id, before_pos); return ret; } @@ -3535,9 +3547,7 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, timestamp = FFMAX(timestamp, st->index_entries[0].timestamp); if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || index == st->nb_index_entries - 1) { - avio_seek(s->pb, st->index_entries[st->nb_index_entries - 1].pos, - SEEK_SET); - matroska->current_id = 0; + matroska_reset_status(matroska, 0, st->index_entries[st->nb_index_entries - 1].pos); while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || index == st->nb_index_entries - 1) { matroska_clear_queue(matroska); if (matroska_parse_cluster(matroska) < 0) @@ -3557,8 +3567,8 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, tracks[i].end_timecode = 0; } - avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET); - matroska->current_id = 0; + /* We seek to a level 1 element, so set the appropriate status. */ + matroska_reset_status(matroska, 0, st->index_entries[index].pos); if (flags & AVSEEK_FLAG_ANY) { st->skip_to_keyframe = 0; matroska->skip_to_timecode = timestamp; @@ -3568,18 +3578,16 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, } matroska->skip_to_keyframe = 1; matroska->done = 0; - matroska->num_levels = 0; ff_update_cur_dts(s, st, st->index_entries[index].timestamp); return 0; err: // slightly hackish but allows proper fallback to // the generic seeking code. + matroska_reset_status(matroska, 0, -1); matroska_clear_queue(matroska); - matroska->current_id = 0; st->skip_to_keyframe = matroska->skip_to_keyframe = 0; matroska->done = 0; - matroska->num_levels = 0; return -1; } @@ -3662,8 +3670,8 @@ static int webm_clusters_start_with_keyframe(AVFormatContext *s) read = ebml_read_length(matroska, matroska->ctx->pb, &cluster_length); if (read < 0) break; - avio_seek(s->pb, cluster_pos, SEEK_SET); - matroska->current_id = 0; + + matroska_reset_status(matroska, 0, cluster_pos); matroska_clear_queue(matroska); if (matroska_parse_cluster(matroska) < 0 || !matroska->queue) { @@ -3677,7 +3685,10 @@ static int webm_clusters_start_with_keyframe(AVFormatContext *s) break; } } - avio_seek(s->pb, before_pos, SEEK_SET); + + /* Restore the status after matroska_read_header: */ + matroska_reset_status(matroska, MATROSKA_ID_CLUSTER, before_pos); + return rv; }