From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id F3FA74C800 for ; Fri, 9 May 2025 23:45:03 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2F8C268C7E2; Sat, 10 May 2025 02:44:33 +0300 (EEST) Received: from mail-oa1-f51.google.com (mail-oa1-f51.google.com [209.85.160.51]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id EE2B268C70A for ; Sat, 10 May 2025 02:43:49 +0300 (EEST) Received: by mail-oa1-f51.google.com with SMTP id 586e51a60fabf-2d0920ce388so1466050fac.0 for ; Fri, 09 May 2025 16:43:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1746834228; x=1747439028; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=q0zZ5xGoTmDgaievCWQmOwBR50IeaKR6HBsGKRWmwx4=; b=Kesi7LZo8w4jRCHJqI7AMU11BPEdEyE8iXjUdGV4tWik/WpbCLyeanWXwfrcEIAaYP nNfQGUmIL7aCbYShezkSm18wL/+jZScZQeMurjdJ4Sfj+NVtvoUUQ6R3Ok4IRcQuTPkR VCtKIqVwBBOaDe0rk0whGi99kspxyhEvwyst1lEZpfCYpGT13SR052PTbouEkZxOxN2Q n4/mK6QTXaoypCSWPTzx3qV/yawCZnUy6Whx/eGz6qrDXgL1snPFdvhXE/mdAsTXKpcH RA63I9HqebfjpieK0RyR12JF2+xN7zCFzOBngIoL3i2yuVAPhj8Kv2i5r9lWmokTfUCb ZNmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1746834228; x=1747439028; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=q0zZ5xGoTmDgaievCWQmOwBR50IeaKR6HBsGKRWmwx4=; b=wn3q7kjo0yOMR9x2fytiX5YjMsd3uNGYeecFTg2xi6OdMEgGPGA28HCwrUbqlM1EFk 1I3SYEsbVk4qsirryen6jZ0G28pQ0/RWh63K2rzS3U6vl7N6f23R8AAX4g+4N8dja2FV 4Bjii8b4ysDCRHYySzoqKlzIww6sAGaERS9CTD3Ttoz2ltLT8+fXjfSOSz/q3H0djWQv dqa39mYm2FM0V1tMDAXA1qt2i0/9nqKVsi4JqfXg2fXVZfVfSvS+qj7t4XemEWZD45wl ON8aC9ZGLcqt1KdqK/xo+JnmH0Ggfj0P0HJYmPkHYW4b5AAjOjz5TDfnVvvMWjPk1qwM EGGw== X-Gm-Message-State: AOJu0Yzbzn3Y0yOEdfEMZJjTsppgKmIWFyLfn7Vk1xvVoMYqSAuntFZZ thwZbceDw0knYZLqqwVroFwauHPr7cYwK+pFs5310tu5xQulkhMifELNvbUE X-Gm-Gg: ASbGncurm4PWNyfpq53Tlj7/KuSFATbh5X3J6h8TR65jb1qbsrclnAohXb2LBupKldC yU4tX0I1MHs/Kq0eM3/a279+kY62Xuzw3wBFZamgQZd9g4WGjAaXAr4tPvHg13wTRyrMjC1KigP SybrD0jFHUfTy6kXLXXDxU532aozbn46po4Cqizc4vqN8gX2/C+pasekwrKpv/PlPLNwq1gcLqy n7COamjWbfAWbuGnn3nmtU1qR7IDD28daS7lBfW15hBJ436fdRSjvw4BnVuxEqj7qr7pfydKf11 UNILy4Qug1cwSNP2cbY7qoBuwMj0OHOZRh97NRUoUcASkfn1u0u3bFT+hxcsnGoGnKxc1kJdKMt xQKJ2z1FVfm5LBX71 X-Google-Smtp-Source: AGHT+IFvnFfG5uDIypwYdGwseEwzK3GP0bhOM8qAfaOQ5scz1Ipu/BUl00fZyGaxqFx+eF0Es8JHGg== X-Received: by 2002:a05:6820:1a0b:b0:604:4846:78a with SMTP id 006d021491bc7-6083ff0ff81mr3694399eaf.2.1746834227842; Fri, 09 May 2025 16:43:47 -0700 (PDT) Received: from localhost.localdomain ([2607:fb90:e33e:5272:5990:2d1e:9f2e:c4de]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6083fe52271sm668499eaf.21.2025.05.09.16.43.46 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Fri, 09 May 2025 16:43:47 -0700 (PDT) From: Romain Beauxis To: ffmpeg-devel@ffmpeg.org Date: Fri, 9 May 2025 18:43:26 -0500 Message-Id: <20250509234327.71039-7-romain.beauxis@gmail.com> X-Mailer: git-send-email 2.39.5 (Apple Git-154) In-Reply-To: <20250509234327.71039-1-romain.beauxis@gmail.com> References: <20250509234327.71039-1-romain.beauxis@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v5 6/7] ogg/vorbis: implement header packet skip in chained ogg bitstreams. 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: Romain Beauxis Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: --- libavcodec/vorbisdec.c | 37 +---- libavformat/oggparsevorbis.c | 174 +++++++++++++-------- tests/ref/fate/ogg-vorbis-chained-meta.txt | 3 - 3 files changed, 117 insertions(+), 97 deletions(-) diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index a778dc6b58..f069ac6ab3 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -1776,39 +1776,17 @@ static int vorbis_decode_frame(AVCodecContext *avctx, AVFrame *frame, GetBitContext *gb = &vc->gb; float *channel_ptrs[255]; int i, len, ret; + const int8_t *new_extradata; + size_t new_extradata_size; ff_dlog(NULL, "packet length %d \n", buf_size); - if (*buf == 1 && buf_size > 7) { - if ((ret = init_get_bits8(gb, buf + 1, buf_size - 1)) < 0) - return ret; - - vorbis_free(vc); - if ((ret = vorbis_parse_id_hdr(vc))) { - av_log(avctx, AV_LOG_ERROR, "Id header corrupt.\n"); - vorbis_free(vc); - return ret; - } - - av_channel_layout_uninit(&avctx->ch_layout); - if (vc->audio_channels > 8) { - avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; - avctx->ch_layout.nb_channels = vc->audio_channels; - } else { - av_channel_layout_copy(&avctx->ch_layout, &ff_vorbis_ch_layouts[vc->audio_channels - 1]); - } - - avctx->sample_rate = vc->audio_samplerate; - return buf_size; - } - - if (*buf == 3 && buf_size > 7) { - av_log(avctx, AV_LOG_DEBUG, "Ignoring comment header\n"); - return buf_size; - } + new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, + &new_extradata_size); - if (*buf == 5 && buf_size > 7 && vc->channel_residues && !vc->modes) { - if ((ret = init_get_bits8(gb, buf + 1, buf_size - 1)) < 0) + if (new_extradata && *new_extradata == 5 && new_extradata_size > 7 && + vc->channel_residues && !vc->modes) { + if ((ret = init_get_bits8(gb, new_extradata + 1, new_extradata_size - 1)) < 0) return ret; if ((ret = vorbis_parse_setup_hdr(vc))) { @@ -1816,7 +1794,6 @@ static int vorbis_decode_frame(AVCodecContext *avctx, AVFrame *frame, vorbis_free(vc); return ret; } - return buf_size; } if (!vc->channel_residues || !vc->modes) { diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 9f50ab9ffc..452728b54d 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -293,6 +293,62 @@ static int vorbis_update_metadata(AVFormatContext *s, int idx) return ret; } +static int vorbis_parse_header(AVFormatContext *s, AVStream *st, + const uint8_t *p, unsigned int psize) +{ + unsigned blocksize, bs0, bs1; + int srate; + int channels; + + if (psize != 30) + return AVERROR_INVALIDDATA; + + p += 7; /* skip "\001vorbis" tag */ + + if (bytestream_get_le32(&p) != 0) /* vorbis_version */ + return AVERROR_INVALIDDATA; + + channels = bytestream_get_byte(&p); + if (st->codecpar->ch_layout.nb_channels && + channels != st->codecpar->ch_layout.nb_channels) { + av_log(s, AV_LOG_ERROR, "Channel change is not supported\n"); + return AVERROR_PATCHWELCOME; + } + st->codecpar->ch_layout.nb_channels = channels; + srate = bytestream_get_le32(&p); + p += 4; // skip maximum bitrate + st->codecpar->bit_rate = bytestream_get_le32(&p); // nominal bitrate + p += 4; // skip minimum bitrate + + blocksize = bytestream_get_byte(&p); + bs0 = blocksize & 15; + bs1 = blocksize >> 4; + + if (bs0 > bs1) + return AVERROR_INVALIDDATA; + if (bs0 < 6 || bs1 > 13) + return AVERROR_INVALIDDATA; + + if (bytestream_get_byte(&p) != 1) /* framing_flag */ + return AVERROR_INVALIDDATA; + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_VORBIS; + + if (srate > 0) { + if (st->codecpar->sample_rate && + srate != st->codecpar->sample_rate) { + av_log(s, AV_LOG_ERROR, "Sample rate change is not supported\n"); + return AVERROR_PATCHWELCOME; + } + + st->codecpar->sample_rate = srate; + avpriv_set_pts_info(st, 64, 1, srate); + } + + return 1; +} + static int vorbis_header(AVFormatContext *s, int idx) { struct ogg *ogg = s->priv_data; @@ -300,6 +356,7 @@ static int vorbis_header(AVFormatContext *s, int idx) struct ogg_stream *os = ogg->streams + idx; struct oggvorbis_private *priv; int pkt_type = os->buf[os->pstart]; + int ret; if (!os->private) { os->private = av_mallocz(sizeof(struct oggvorbis_private)); @@ -327,56 +384,18 @@ static int vorbis_header(AVFormatContext *s, int idx) priv->len[pkt_type >> 1] = os->psize; priv->packet[pkt_type >> 1] = av_memdup(os->buf + os->pstart, os->psize); + if (!priv->packet[pkt_type >> 1]) return AVERROR(ENOMEM); - if (os->buf[os->pstart] == 1) { - const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */ - unsigned blocksize, bs0, bs1; - int srate; - int channels; - - if (os->psize != 30) - return AVERROR_INVALIDDATA; - - if (bytestream_get_le32(&p) != 0) /* vorbis_version */ - return AVERROR_INVALIDDATA; - - channels = bytestream_get_byte(&p); - if (st->codecpar->ch_layout.nb_channels && - channels != st->codecpar->ch_layout.nb_channels) { - av_log(s, AV_LOG_ERROR, "Channel change is not supported\n"); - return AVERROR_PATCHWELCOME; - } - st->codecpar->ch_layout.nb_channels = channels; - srate = bytestream_get_le32(&p); - p += 4; // skip maximum bitrate - st->codecpar->bit_rate = bytestream_get_le32(&p); // nominal bitrate - p += 4; // skip minimum bitrate - - blocksize = bytestream_get_byte(&p); - bs0 = blocksize & 15; - bs1 = blocksize >> 4; - - if (bs0 > bs1) - return AVERROR_INVALIDDATA; - if (bs0 < 6 || bs1 > 13) - return AVERROR_INVALIDDATA; - - if (bytestream_get_byte(&p) != 1) /* framing_flag */ - return AVERROR_INVALIDDATA; - - st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = AV_CODEC_ID_VORBIS; - - if (srate > 0) { - st->codecpar->sample_rate = srate; - avpriv_set_pts_info(st, 64, 1, srate); - } - } else if (os->buf[os->pstart] == 3) { + + if (pkt_type == 1) + return vorbis_parse_header(s, st, os->buf + os->pstart, os->psize); + + if (pkt_type == 3) { if (vorbis_update_metadata(s, idx) >= 0 && priv->len[1] > 10) { unsigned new_len; - int ret = ff_replaygain_export(st, st->metadata); + ret = ff_replaygain_export(st, st->metadata); if (ret < 0) return ret; @@ -388,25 +407,25 @@ static int vorbis_header(AVFormatContext *s, int idx) priv->len[1] = new_len; } } - } else { - int ret; - if (priv->vp) - return AVERROR_INVALIDDATA; + return 1; + } - ret = fixup_vorbis_headers(s, priv, &st->codecpar->extradata); - if (ret < 0) { - st->codecpar->extradata_size = 0; - return ret; - } - st->codecpar->extradata_size = ret; + if (priv->vp) + return AVERROR_INVALIDDATA; - priv->vp = av_vorbis_parse_init(st->codecpar->extradata, st->codecpar->extradata_size); - if (!priv->vp) { - av_freep(&st->codecpar->extradata); - st->codecpar->extradata_size = 0; - return AVERROR_UNKNOWN; - } + ret = fixup_vorbis_headers(s, priv, &st->codecpar->extradata); + if (ret < 0) { + st->codecpar->extradata_size = 0; + return ret; + } + st->codecpar->extradata_size = ret; + + priv->vp = av_vorbis_parse_init(st->codecpar->extradata, st->codecpar->extradata_size); + if (!priv->vp) { + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 0; + return AVERROR_UNKNOWN; } return 1; @@ -418,6 +437,8 @@ static int vorbis_packet(AVFormatContext *s, int idx) struct ogg_stream *os = ogg->streams + idx; struct oggvorbis_private *priv = os->private; int duration, flags = 0; + int skip_packet = 0; + int ret; if (!priv->vp) return AVERROR_INVALIDDATA; @@ -480,10 +501,35 @@ static int vorbis_packet(AVFormatContext *s, int idx) if (duration < 0) { os->pflags |= AV_PKT_FLAG_CORRUPT; return 0; - } else if (flags & VORBIS_FLAG_COMMENT) { - vorbis_update_metadata(s, idx); + } + + if (flags & VORBIS_FLAG_HEADER) { + ret = vorbis_parse_header(s, s->streams[idx], os->buf + os->pstart, os->psize); + if (ret < 0) + return ret; + + skip_packet = 1; + } + + if (flags & VORBIS_FLAG_COMMENT) { + ret = vorbis_update_metadata(s, idx); + if (ret < 0) + return ret; + flags = 0; + skip_packet = 1; } + + if (flags & VORBIS_FLAG_SETUP) { + ret = av_reallocp(&os->new_extradata, os->psize); + if (ret < 0) + return ret; + + memcpy(os->new_extradata, os->buf + os->pstart, os->psize); + os->new_extradata_size = os->psize; + skip_packet = 1; + } + os->pduration = duration; } @@ -505,7 +551,7 @@ static int vorbis_packet(AVFormatContext *s, int idx) priv->final_duration += os->pduration; } - return 0; + return skip_packet; } const struct ogg_codec ff_vorbis_codec = { diff --git a/tests/ref/fate/ogg-vorbis-chained-meta.txt b/tests/ref/fate/ogg-vorbis-chained-meta.txt index b7a97c90e2..1206f86c1f 100644 --- a/tests/ref/fate/ogg-vorbis-chained-meta.txt +++ b/tests/ref/fate/ogg-vorbis-chained-meta.txt @@ -6,10 +6,7 @@ Stream ID: 0, frame PTS: 128, metadata: N/A Stream ID: 0, packet PTS: 704, packet DTS: 704 Stream ID: 0, frame PTS: 704, metadata: N/A Stream ID: 0, packet PTS: 0, packet DTS: 0 -Stream ID: 0, packet PTS: 0, packet DTS: 0 Stream ID: 0, new metadata: encoder=Lavc61.19.100 libvorbis:title=Second Stream -Stream ID: 0, packet PTS: 0, packet DTS: 0 -Stream ID: 0, packet PTS: 0, packet DTS: 0 Stream ID: 0, frame PTS: 0, metadata: N/A Stream ID: 0, packet PTS: 128, packet DTS: 128 Stream ID: 0, frame PTS: 128, metadata: N/A -- 2.39.5 (Apple Git-154) _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".