From patchwork Tue Jul 9 17:23:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jai Luthra X-Patchwork-Id: 13873 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 A8C8E44794E for ; Tue, 9 Jul 2019 20:51:45 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 77DCB68AAE7; Tue, 9 Jul 2019 20:51:45 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pg1-f196.google.com (mail-pg1-f196.google.com [209.85.215.196]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id B2FF168A2A9 for ; Tue, 9 Jul 2019 20:51:38 +0300 (EEST) Received: by mail-pg1-f196.google.com with SMTP id p10so9834195pgn.1 for ; Tue, 09 Jul 2019 10:51:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jailuthra-in.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=8oXFGTVfrBUCzdVVO9F+vM43m5ehLFknh7kSHrl1+0w=; b=wPi0qXKQfGEjf37ooNIhiOLjc/h9Awa/J9dBezwTCjcKnmhp3J2xj7VhRIMXiEZd6t 5ZtSopYnY1NJ1wMocdRMV4fmQQYb8aA5lO13WDnHwJjtNKw8cmdh88nXKAepfSMuop1O 0CXvaIN+hB99z7u9ur6ZOxxOxDPYKyiY/3BU13UlwveFr1LHdoe78oZhM5HkDxCsWSRc Y5bgu2KbB3FwMOBxhF8jrslCR/OQeyRLRmo21bjgJqbAo/lfrTKtXFTaO5uA3CQK/fJd AlZAJ2rM2GXj3bIlM/du8nEHZvYdp7KWCbVYHqV5JL/1qrG1wx/2yhoonVw9o4dGXxVx i+1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=8oXFGTVfrBUCzdVVO9F+vM43m5ehLFknh7kSHrl1+0w=; b=prfAHongLO2z0FFoh2clvheGP7vC/tzTEiV3s/29bkJpnKzYPRG4apVdqSZlZnY62a rNlkpqaxQ+yn5OwIq4iN7CMdzYLDDRQ2dBgsHgX2plX6oJA26wJPXbqBO7fBLKRAJKPP bOGA8txMBV0yhPsdChrZBZUeIgyRMmX65o7DrrWkFSdauwySTueNAMU7rkTNIbUJJyrP vrAEnzlE2wDs84QQJLF4Zf1FSE0b4kCxPQF7fxchxPz6DkX56jTcR+kzQIZzzLK22qCs SISYUEbnxkfEk1MCZu6yxsn1YtJwPKh2Waw8gtEpgDEcLLWbzFPauTSwMLYsfo4rWocm S5OA== X-Gm-Message-State: APjAAAW/YZK2Q8uQw8KdQqmilSfTxNJJ6QIPiQ0zcYAaecls/Z4G8Wj2 hyuwO1So6nf0sDSWOoZY1umlD1h9nY8= X-Google-Smtp-Source: APXvYqwV8Ls5NDEOMNAiekSR9rgc4UrAEd0P5hz0hi+wTa0zxoJKSOrtW4Op9CSYeMoICPE08xEPOA== X-Received: by 2002:a63:6089:: with SMTP id u131mr32756812pgb.314.1562693005676; Tue, 09 Jul 2019 10:23:25 -0700 (PDT) Received: from localhost.localdomain ([122.180.207.198]) by smtp.googlemail.com with ESMTPSA id f17sm18140359pgv.16.2019.07.09.10.23.24 for (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 09 Jul 2019 10:23:25 -0700 (PDT) From: Jai Luthra To: ffmpeg-devel@ffmpeg.org Date: Tue, 9 Jul 2019 22:53:02 +0530 Message-Id: <20190709172302.14886-1-me@jailuthra.in> X-Mailer: git-send-email 2.22.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] mlpenc: fix lossless failures, add sanity checks 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: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Jai Luthra --- libavcodec/mlpenc.c | 72 +++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c index deb171645c..09a8336b47 100644 --- a/libavcodec/mlpenc.c +++ b/libavcodec/mlpenc.c @@ -1,6 +1,7 @@ /** * MLP encoder * Copyright (c) 2008 Ramiro Polla + * Copyright (c) 2016-2019 Jai Luthra * * This file is part of FFmpeg. * @@ -26,6 +27,7 @@ #include "libavutil/crc.h" #include "libavutil/avstring.h" #include "libavutil/samplefmt.h" +#include "libavutil/avassert.h" #include "mlp.h" #include "lpc.h" @@ -93,8 +95,8 @@ typedef struct BestOffset { int16_t max; } BestOffset; -#define HUFF_OFFSET_MIN -16384 -#define HUFF_OFFSET_MAX 16383 +#define HUFF_OFFSET_MIN (-16384) +#define HUFF_OFFSET_MAX ( 16383) /** Number of possible codebooks (counting "no codebooks") */ #define NUM_CODEBOOKS 4 @@ -466,9 +468,6 @@ static void default_decoding_params(MLPEncodeContext *ctx, */ static int inline number_sbits(int number) { - if (number < 0) - number++; - return av_log2(FFABS(number)) + 1 + !!number; } @@ -807,7 +806,7 @@ static void write_major_sync(MLPEncodeContext *ctx, uint8_t *buf, int buf_size) static void write_restart_header(MLPEncodeContext *ctx, PutBitContext *pb) { RestartHeader *rh = ctx->cur_restart_header; - int32_t lossless_check = xor_32_to_8(rh->lossless_check_data); + uint8_t lossless_check = xor_32_to_8(rh->lossless_check_data); unsigned int start_count = put_bits_count(pb); PutBitContext tmpb; uint8_t checksum; @@ -1016,12 +1015,10 @@ static void write_block_data(MLPEncodeContext *ctx, PutBitContext *pb) codebook_index [ch] = cp->codebook - 1; sign_huff_offset[ch] = cp->huff_offset; - sign_shift = lsb_bits[ch] - 1; + sign_shift = lsb_bits[ch] + (cp->codebook ? 2 - cp->codebook : -1); - if (cp->codebook > 0) { + if (cp->codebook > 0) sign_huff_offset[ch] -= 7 << lsb_bits[ch]; - sign_shift += 3 - cp->codebook; - } /* Unsign if needed. */ if (sign_shift >= 0) @@ -1031,7 +1028,6 @@ static void write_block_data(MLPEncodeContext *ctx, PutBitContext *pb) for (i = 0; i < dp->blocksize; i++) { for (ch = rh->min_channel; ch <= rh->max_channel; ch++) { int32_t sample = *sample_buffer++ >> dp->quant_step_size[ch]; - sample -= sign_huff_offset[ch]; if (codebook_index[ch] >= 0) { @@ -1251,7 +1247,7 @@ static void input_data_internal(MLPEncodeContext *ctx, const uint8_t *samples, uint32_t abs_sample; int32_t sample; - sample = is24 ? *samples_32++ >> 8 : *samples_16++ << 8; + sample = is24 ? *samples_32++ >> 8 : *samples_16++ * 256U; /* TODO Find out if number_sbits can be used for negative values. */ abs_sample = FFABS(sample); @@ -1591,7 +1587,7 @@ static void no_codebook_bits(MLPEncodeContext *ctx, { DecodingParams *dp = ctx->cur_decoding_params; int16_t offset; - int32_t unsign; + int32_t unsign = 0; uint32_t diff; int lsb_bits; @@ -1607,7 +1603,8 @@ static void no_codebook_bits(MLPEncodeContext *ctx, lsb_bits = number_sbits(diff) - 1; - unsign = 1 << (lsb_bits - 1); + if (lsb_bits > 0) + unsign = 1 << (lsb_bits - 1); /* If all samples are the same (lsb_bits == 0), offset must be * adjusted because of sign_shift. */ @@ -1699,7 +1696,7 @@ static inline void codebook_bits(MLPEncodeContext *ctx, offset_min = FFMAX(min, HUFF_OFFSET_MIN); offset_max = FFMIN(max, HUFF_OFFSET_MAX); - for (;;) { + while (offset <= offset_max && offset >= offset_min) { BestOffset temp_bo; codebook_bits_offset(ctx, channel, codebook, @@ -1709,6 +1706,7 @@ static inline void codebook_bits(MLPEncodeContext *ctx, if (temp_bo.bitcount < previous_count) { if (temp_bo.bitcount < bo->bitcount) *bo = temp_bo; + av_assert0(bo->offset <= HUFF_OFFSET_MAX && bo->offset >= HUFF_OFFSET_MIN); is_greater = 0; } else if (++is_greater >= ctx->max_codebook_search) @@ -1718,12 +1716,8 @@ static inline void codebook_bits(MLPEncodeContext *ctx, if (direction) { offset = temp_bo.max + 1; - if (offset > offset_max) - break; } else { offset = temp_bo.min - 1; - if (offset < offset_min) - break; } } } @@ -1796,11 +1790,11 @@ static void determine_bits(MLPEncodeContext *ctx) #define SAMPLE_MAX(bitdepth) ((1 << (bitdepth - 1)) - 1) #define SAMPLE_MIN(bitdepth) (~SAMPLE_MAX(bitdepth)) -#define MSB_MASK(bits) (-1u << bits) +#define MSB_MASK(bits) (-(1u << (bits))) /** Applies the filter to the current samples, and saves the residual back * into the samples buffer. If the filter is too bad and overflows the - * maximum amount of bits allowed (16 or 24), the samples buffer is left as is and + * maximum amount of bits allowed (24), the samples buffer is left as is and * the function returns -1. */ static int apply_filter(MLPEncodeContext *ctx, unsigned int channel) @@ -1836,7 +1830,7 @@ static int apply_filter(MLPEncodeContext *ctx, unsigned int channel) int32_t sample = *sample_buffer; unsigned int order; int64_t accum = 0; - int32_t residual; + int64_t residual; for (filter = 0; filter < NUM_FILTERS; filter++) { int32_t *fcoeff = ctx->cur_channel_params[channel].coeff[filter]; @@ -1848,11 +1842,11 @@ static int apply_filter(MLPEncodeContext *ctx, unsigned int channel) accum >>= filter_shift; residual = sample - (accum & mask); - if (residual < SAMPLE_MIN(ctx->wordlength) || residual > SAMPLE_MAX(ctx->wordlength)) + if (residual < SAMPLE_MIN(24) || residual > SAMPLE_MAX(24)) return -1; filter_state_buffer[FIR][i] = sample; - filter_state_buffer[IIR][i] = residual; + filter_state_buffer[IIR][i] = (int32_t) residual; sample_buffer += ctx->num_channels; } @@ -1882,7 +1876,7 @@ static void apply_filters(MLPEncodeContext *ctx) * Clear filter params and update state. */ set_filter_params(ctx, channel, FIR, 1); set_filter_params(ctx, channel, IIR, 1); - apply_filter(ctx, channel); + av_assert0(apply_filter(ctx, channel) >= 0); } } } @@ -1897,8 +1891,8 @@ static void generate_2_noise_channels(MLPEncodeContext *ctx) for (i = 0; i < ctx->number_of_samples; i++) { uint16_t seed_shr7 = seed >> 7; - *sample_buffer++ = ((int8_t)(seed >> 15)) << rh->noise_shift; - *sample_buffer++ = ((int8_t) seed_shr7) << rh->noise_shift; + *sample_buffer++ = ((int8_t)(seed >> 15)) * (1 << rh->noise_shift); + *sample_buffer++ = ((int8_t) seed_shr7) * (1 << rh->noise_shift); seed = (seed << 16) ^ seed_shr7 ^ (seed_shr7 << 5); @@ -2069,9 +2063,10 @@ static void set_best_codebook(MLPEncodeContext *ctx) best_codebook = *best_path++ - ZERO_PATH; cur_bo = &ctx->best_offset[index][channel][best_codebook]; - cp->huff_offset = cur_bo->offset; - cp->huff_lsbs = cur_bo->lsb_bits + dp->quant_step_size[channel]; - cp->codebook = best_codebook; + cp->huff_offset = cur_bo->offset; + cp->sign_huff_offset = -(1 << 23); + cp->huff_lsbs = cur_bo->lsb_bits + dp->quant_step_size[channel]; + cp->codebook = best_codebook; } } } @@ -2210,8 +2205,15 @@ static void process_major_frame(MLPEncodeContext *ctx) generate_2_noise_channels(ctx); rematrix_channels (ctx); - for (channel = rh->min_channel; channel <= rh->max_channel; channel++) - apply_filter(ctx, channel); + for (channel = rh->min_channel; channel <= rh->max_channel; channel++) { + if (apply_filter(ctx, channel) < 0) { + /* Filter is horribly wrong. + * Clear filter params and update state. */ + set_filter_params(ctx, channel, FIR, 1); + set_filter_params(ctx, channel, IIR, 1); + av_assert0(apply_filter(ctx, channel) >= 0); + } + } } } @@ -2277,7 +2279,7 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (restart_frame) { set_major_params(ctx); if (ctx->min_restart_interval != ctx->max_restart_interval) - process_major_frame(ctx); + process_major_frame(ctx); } if (ctx->min_restart_interval == ctx->max_restart_interval) @@ -2391,7 +2393,7 @@ AVCodec ff_mlp_encoder = { .encode2 = mlp_encode_frame, .close = mlp_encode_close, .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, - .sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE}, + .sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE}, .supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0}, .channel_layouts = ff_mlp_channel_layouts, }; @@ -2407,7 +2409,7 @@ AVCodec ff_truehd_encoder = { .encode2 = mlp_encode_frame, .close = mlp_encode_close, .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, - .sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE}, + .sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE}, .supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0}, .channel_layouts = (const uint64_t[]) {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0}, };