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 ESMTP id 7279E40592 for ; Sun, 27 Mar 2022 13:40:03 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9707668B24E; Sun, 27 Mar 2022 16:40:00 +0300 (EEST) Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4BE2068A7BB for ; Sun, 27 Mar 2022 16:39:54 +0300 (EEST) Received: by mail-ej1-f41.google.com with SMTP id o10so23721338ejd.1 for ; Sun, 27 Mar 2022 06:39:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ti8g9kmKp7+0nLu4vXBmAJiNbuUWYjkxtEEUPiwnhZI=; b=oRIk6BYn9ETOy5Dl1xu7GPfrqI7uJbIsJLStAU1THjuWj+qVQDzsRqOjW0Hz1Q7+4F fscjyfeJkQ+lHhHBIg5R6oSVt+XU/WhvMeA1VWwnwN6fcwf/6M/T5rnZfyzbzWFQ67MY zl3RvNCLqCKOGbEckE8rSO4HzGikKBtWqORqpBhXVbiDbjiTXId2AZ7uxmBI3UtQI/9x Sugr3f+3lpCj5ksmNyQWUbLZWiazmJ8YnqTbXjuLLwfyqu8ErRxdZbJJntO6Fr2gbuhb wV7TOuyXlqMWiOvf3rqxc4ux722YABh76XqGAWGJ6cTu0f16OT7eZIp5nb+7m4GrBBza yI/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ti8g9kmKp7+0nLu4vXBmAJiNbuUWYjkxtEEUPiwnhZI=; b=goPiZ6PJIJvxsdp7m3qJ7pEqBWyR8QoonGkzuWk4hQNcb28iTaYe6ULbuotBysZSUo 0yi5vZp1ChyM6WcekK8/m0v1m4IcUDtQHg4iDR8MH1z9OM8+4yZwTfC6UUGYd5Y8vZDE xxOx13opIPYZHbRWfwUHCkmkKbVpQQBbHnMcY4HBF8cBUvE2xkDWF1H8Xc9HhaPHwnO+ yY0BnYF2wYTHMueaDe4rWSKLKgs4OiTHrKeYaF/t4uMWEDlLmnHLOTvz2lKs83KlAo5T h4A+kmBgoXbVAj+E5WKn3gV73Q9JRU7M2hFMt1d7rRCglGbplgzyoU/n023nj+WtDquY /G6Q== X-Gm-Message-State: AOAM532+AnN8/zSjwGOGOhopkypFfkKRuesWXfy68pVnT7QCNeF0zVT9 F4LDEIoYRMzZOOhQjmcK4xhdsfTmUuM= X-Google-Smtp-Source: ABdhPJyytPNgnWBr/Xb6HmYOGOpuNAKVrbvIGyQvf5zTNjQC6VIpEJoryrjNRKf73ltaXw2y9tq4Vg== X-Received: by 2002:a17:907:7f94:b0:6da:64ec:fabc with SMTP id qk20-20020a1709077f9400b006da64ecfabcmr22118524ejc.717.1648388393073; Sun, 27 Mar 2022 06:39:53 -0700 (PDT) Received: from localhost.localdomain (92-64-99-37.biz.kpn.net. [92.64.99.37]) by smtp.googlemail.com with ESMTPSA id yy18-20020a170906dc1200b006d6e5c75029sm4585226ejb.187.2022.03.27.06.39.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Mar 2022 06:39:52 -0700 (PDT) From: Martijn van Beurden To: ffmpeg-devel@ffmpeg.org Date: Sun, 27 Mar 2022 15:39:33 +0200 Message-Id: <20220327133933.43039-1-mvanb1@gmail.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] Add decoding of > 32-bit residuals to FLAC 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: Martijn van Beurden 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: The size of residuals in a FLAC file coding for 24-bit PCM can exceed the range of a 32-bit signed integer. One pathological example with residuals exceeding [-2^33,2^33) can be found here: http://www.audiograaf.nl/misc_stuff/Extreme%20residual%20LPC%20order%2014.flac The theorectical maximum bit depth for a residual in a FLAC file is 32 + 1 + 15 + 5 - 0 = 53 bit (max bit depth + extra bit for side channel + max lpc coeff precision + log2(max_order) - min lpc shift) This patch adds detection of the possibilty of such residuals occuring and an alternate data path wide enough to handle them --- libavcodec/flacdec.c | 107 ++++++++++++++++++++++++++++++++++++++----- libavcodec/golomb.h | 56 ++++++++++++++++++++++ 2 files changed, 152 insertions(+), 11 deletions(-) diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index dd6026f9de..3be1b63411 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -64,6 +64,8 @@ typedef struct FLACContext { uint8_t *decoded_buffer; unsigned int decoded_buffer_size; int buggy_lpc; ///< use workaround for old lavc encoded files + int64_t *residual64; ///< to keep residuals exceeding int32_t + unsigned int residual64_size; FLACDSPContext dsp; } FLACContext; @@ -149,6 +151,10 @@ static int allocate_buffers(FLACContext *s) if (!s->decoded_buffer) return AVERROR(ENOMEM); + av_fast_malloc(&s->residual64, &s->residual64_size, 8*s->flac_stream_info.max_blocksize); + if (!s->residual64) + return AVERROR(ENOMEM); + ret = av_samples_fill_arrays((uint8_t **)s->decoded, NULL, s->decoded_buffer, s->flac_stream_info.channels, @@ -279,6 +285,66 @@ static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order) return 0; } +static int decode_residuals64(FLACContext *s, int64_t *decoded, int pred_order) +{ + GetBitContext gb = s->gb; + int i, tmp, partition, method_type, rice_order; + int rice_bits, rice_esc; + int samples; + + method_type = get_bits(&gb, 2); + rice_order = get_bits(&gb, 4); + + samples = s->blocksize >> rice_order; + rice_bits = 4 + method_type; + rice_esc = (1 << rice_bits) - 1; + + decoded += pred_order; + i = pred_order; + + if (method_type > 1) { + av_log(s->avctx, AV_LOG_ERROR, "illegal residual coding method %d\n", + method_type); + return AVERROR_INVALIDDATA; + } + + if (samples << rice_order != s->blocksize) { + av_log(s->avctx, AV_LOG_ERROR, "invalid rice order: %i blocksize %i\n", + rice_order, s->blocksize); + return AVERROR_INVALIDDATA; + } + + if (pred_order > samples) { + av_log(s->avctx, AV_LOG_ERROR, "invalid predictor order: %i > %i\n", + pred_order, samples); + return AVERROR_INVALIDDATA; + } + + for (partition = 0; partition < (1 << rice_order); partition++) { + tmp = get_bits(&gb, rice_bits); + if (tmp == rice_esc) { + tmp = get_bits(&gb, 5); + for (; i < samples; i++) + *decoded++ = get_sbits_long(&gb, tmp); + } else { + for (; i < samples; i++) { + int64_t v = get_sr_golomb64_flac(&gb, tmp, 1); + if (v == INT64_MAX) { + av_log(s->avctx, AV_LOG_ERROR, "invalid residual\n"); + return AVERROR_INVALIDDATA; + } + + *decoded++ = v; + } + } + i = 0; + } + + s->gb = gb; + + return 0; +} + static int decode_subframe_fixed(FLACContext *s, int32_t *decoded, int pred_order, int bps) { @@ -358,6 +424,21 @@ static void lpc_analyze_remodulate(SUINT32 *decoded, const int coeffs[32], } } +static void lpc_residual64(int32_t *decoded, const int64_t *residual, + const int coeffs[32], int pred_order, + int qlevel, int len) +{ + int i, j; + + for (i = pred_order; i < len; i++, decoded++) { + int64_t sum = 0; + for (j = 0; j < pred_order; j++) + sum += (int64_t)coeffs[j] * decoded[j]; + decoded[j] = residual[i] + (sum >> qlevel); + } + +} + static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order, int bps) { @@ -386,19 +467,23 @@ static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order, coeffs[pred_order - i - 1] = get_sbits(&s->gb, coeff_prec); } - if ((ret = decode_residuals(s, decoded, pred_order)) < 0) - return ret; - - if ( ( s->buggy_lpc && s->flac_stream_info.bps <= 16) - || ( !s->buggy_lpc && bps <= 16 - && bps + coeff_prec + av_log2(pred_order) <= 32)) { - s->dsp.lpc16(decoded, coeffs, pred_order, qlevel, s->blocksize); + if (bps + coeff_prec + av_log2(pred_order) - qlevel <= 32) { + if ((ret = decode_residuals(s, decoded, pred_order)) < 0) + return ret; + if ( ( s->buggy_lpc && s->flac_stream_info.bps <= 16) + || ( !s->buggy_lpc && bps <= 16 + && bps + coeff_prec + av_log2(pred_order) <= 32)) { + s->dsp.lpc16(decoded, coeffs, pred_order, qlevel, s->blocksize); + } else { + s->dsp.lpc32(decoded, coeffs, pred_order, qlevel, s->blocksize); + if (s->flac_stream_info.bps <= 16) + lpc_analyze_remodulate(decoded, coeffs, pred_order, qlevel, s->blocksize, bps); + } } else { - s->dsp.lpc32(decoded, coeffs, pred_order, qlevel, s->blocksize); - if (s->flac_stream_info.bps <= 16) - lpc_analyze_remodulate(decoded, coeffs, pred_order, qlevel, s->blocksize, bps); + if ((ret = decode_residuals64(s, s->residual64, pred_order)) < 0) + return ret; + lpc_residual64(decoded, s->residual64, coeffs, pred_order, qlevel, s->blocksize); } - return 0; } diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h index 164c2583b6..5ebcdda059 100644 --- a/libavcodec/golomb.h +++ b/libavcodec/golomb.h @@ -543,6 +543,62 @@ static inline int get_sr_golomb_flac(GetBitContext *gb, int k, int limit, return (v >> 1) ^ -(v & 1); } +static inline int64_t get_sr_golomb64_flac(GetBitContext *gb, int k, + int esc_len) +{ + uint64_t buf; + int log; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + log = av_log2(buf); + + av_assert2(k <= 31); + + if (log - k >= 64 - MIN_CACHE_BITS + (MIN_CACHE_BITS == 64)) { + buf >>= log - k; + buf += (62U - log) << k; + LAST_SKIP_BITS(re, gb, 64 + k - log); + CLOSE_READER(re, gb); + } else { + int64_t i; + for (i = 0; SHOW_UBITS(re, gb, MIN_CACHE_BITS) == 0; i += MIN_CACHE_BITS) { + if (gb->size_in_bits <= re_index) { + CLOSE_READER(re, gb); + return INT64_MAX; + } + LAST_SKIP_BITS(re, gb, MIN_CACHE_BITS); + UPDATE_CACHE(re, gb); + } + for (; SHOW_UBITS(re, gb, 1) == 0; i++) { + SKIP_BITS(re, gb, 1); + } + LAST_SKIP_BITS(re, gb, 1); + UPDATE_CACHE(re, gb); + + if (k) { + if (k > MIN_CACHE_BITS - 1) { + buf = SHOW_UBITS(re, gb, 16) << (k-16); + LAST_SKIP_BITS(re, gb, 16); + UPDATE_CACHE(re, gb); + buf |= SHOW_UBITS(re, gb, k-16); + LAST_SKIP_BITS(re, gb, k-16); + } else { + buf = SHOW_UBITS(re, gb, k); + LAST_SKIP_BITS(re, gb, k); + } + } else { + buf = 0; + } + + buf += (i << k); + CLOSE_READER(re, gb); + } + return (buf >> 1) ^ -(buf & 1); +} + /** * read unsigned golomb rice code (shorten). */ -- 2.30.2 _______________________________________________ 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".