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 3C5EB44A57 for ; Tue, 4 Oct 2022 15:12:30 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7128268BC66; Tue, 4 Oct 2022 18:12:28 +0300 (EEST) Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05olkn2073.outbound.protection.outlook.com [40.92.90.73]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8BA1268BBEB for ; Tue, 4 Oct 2022 18:12:22 +0300 (EEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=QsT1jUfYo147Obii9T00Lj19pESGOE/HRFZ9HO2uWwBkWwu+ETPrCiBQ76XwxbawQvt5aoLIXAAcY3RnbKrX1l9ElSPvmDKYnvsXkxlE4dMm4Nu7JoiLXS+USIl4qnREEqar58bxBUy19wmUPjEqShsDfQRqaFXi6ux+EcuZ+yJ3NGHlOEmg/9eGlkb23LkuJeSIQPksFAVDgG4ZdxJWZ5HVnCM9POmo6ecE/Arfv8HwSp6DL/hK3ATbgqst6fY2iq6WIekAKVkE+YUaiJylx2qXSCyc0BYOnUaeGwpLEUmS55SFuko5AjRExZUVZSAlNaDDqQRZfUR7OSnBAi+1Tg== 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=CgAc+A6sl1vRwnTBP9LOYxXqsqbSxU04DDL7PlROlIc=; b=l+mbKsmdEVmaEyE8efj3lfyOzSyQSeBFZ/b/TkU4I2b8QiJOmcRnD5LRnoSOttFCrss0ADwa2nk3LtuArlcOkk5nNzZ7Wb6qUjSj467neuqiYNcbgfUGfDHIDUX8VswQcuBCeD6nuSxNWFoyM+ttdjm6W1WeDsFaPPHKPFMHEcjRUu4wJiAqWUNha32iHtqUUVttjGHu2Dd1HnTIN6BvNIWsF6h6pEgofZ9rTVcaR2QN12jhSjC5/vjRqrW5pNR6dycTAc5it2HAL9Dq5wIQGojHHbpT6l+9plumU1LtXKAUFIQATxsLvVOwESW+g0DPcEkzsulcBJFo2UCDXNZlNQ== 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=CgAc+A6sl1vRwnTBP9LOYxXqsqbSxU04DDL7PlROlIc=; b=sf4JyyhnCdj36QygLPAYSlUf8B11jT65Jcs3Dly2We8Gy9cPuUFKlU3jvQ8Hf0Z3zPnTwsWGxF5B3LITPBNoyrqo+Ke3TPSFDdShFLgoD035/jXnW2xpNhi8L6kn9U3yWqER5iKY4WXr+izatmU6JcNZFJNVDHcgM6tvOmE97DB/RFd7+wPjqcdyJIeHrWf+VgB7xzhunRFeM6NSvZvXDuGv8j571v9qKkuyaPOnYEMfJcvLot3sb6A67gilG7yAvsngmFzLMZNYhqIjFoUFEwpjwgkRxY2iofcKQJEsirmKbHtVy7j8czyMh/ke8c49rwI3/99RJy7DTVnIIqyQzg== Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) by AS8P250MB0282.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:371::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5676.31; Tue, 4 Oct 2022 15:12:21 +0000 Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::85ac:1b92:90f:dc18]) by AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::85ac:1b92:90f:dc18%4]) with mapi id 15.20.5676.028; Tue, 4 Oct 2022 15:12:21 +0000 Message-ID: Date: Tue, 4 Oct 2022 17:12:27 +0200 Content-Language: en-US To: ffmpeg-devel@ffmpeg.org References: <20220916201415.2583646-1-mvanb1@gmail.com> <20220916201415.2583646-3-mvanb1@gmail.com> From: Andreas Rheinhardt In-Reply-To: <20220916201415.2583646-3-mvanb1@gmail.com> X-TMN: [XWeIR6nzTTz+SsxTriachVCpnvC5O5lvNSxogkTgiIs=] X-ClientProxiedBy: ZR0P278CA0111.CHEP278.PROD.OUTLOOK.COM (2603:10a6:910:20::8) To AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) X-Microsoft-Original-Message-ID: <2c85464e-b015-66b4-c9ba-d42094920706@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AS8P250MB0744:EE_|AS8P250MB0282:EE_ X-MS-Office365-Filtering-Correlation-Id: 9fd8817c-93f6-4279-0d92-08daa61ad575 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 1LyTXBsVob1RgarFTxEa+a//kwOTnAe7s1DlHupfsDnFUS3ujEoYBtZ7ijTeXk5G3xLuReehkMv1BXnL2PjEA8fPZR7PlxG8tdZChOgRH5vcsCdIhSIL+2srt7CqwqZ2wpAdMWh5/1gopKCjgnWDYBA622IA9/3ysSyuc/WlHWoRKr/SMNtATH6h7qeEDIkk+urmKUaaT9BZUEZpQf5fUvBw4BgmY/D+9gkqvaiMPV9vcQFar1mvZ86DwNTqNbhXYBkxlSVEfkdq/yKybKCtkAFAWCObHfZwdxFxibODugS9LDZZ2RTE5XL4hN1vsdpNL+Vh5lERPbgpEFo6Pv2iDoc+rhv6yI/UvlxN5ZVrXWLo125uMccy4VKoy89JMpQnptNgtdMg8NG/nk3VnZcQgUT8lvj8+1ILJedNCgMijmtPk6iQryVBujQvrBH1Ru8nIMWNIyvErNuL9WtXc8KhvdFpBO3/EXXmpezbLqh97n7cgMQZ+lvroStGvolGvs+rW/D8IDrPeYWCcrJcMSAc94EXyTeGxRnC6GNZzK7Lt6b3RElwh2me82EzTltuBVieovbeSwen01j/5RP2AcR2HV+SV+Xi3YPUeI2J2tslCFO0chlHfvgdCEZPCwGbgtFwaVNzzcwXkr9IAgHibQ8G1mlzxcBRbNajBdp0e+RDOC58Baq0Frm8gkKxx0O0E0WG X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?bi8yaFhZQldvUk15eTI0ajNwV2FucE9zSlU2TEIrVVBaQWVRQTdnbVgyZkZu?= =?utf-8?B?bnNqaGhLcXBoQVd4QldPWlU5V1NiU3pVc1VMNE5FVy84UU0xWGtSNEFPd1N1?= =?utf-8?B?TnFEODNIS3paR0ZIV2x3d1ZRRWtiaE5CVWxVZ3VPb05Nc1hzTUhjUitDNTc3?= =?utf-8?B?SEs2ckdLSXlXdEZYZDhUZjF1Unl3NnR5REs2aHprbVhRUVF4QXFwKzBORGJM?= =?utf-8?B?ZzhaTUsyNWtNUGRjNlZPOTJHRW9GQUl0MFVhUjJxNEJOZEdaTU13T2Zkeitu?= =?utf-8?B?VnVwYllhSGlYdzVqZlRDZThYcjR1SERMRy9IbVpNeG5rbC9BSTAyRVczcFVn?= =?utf-8?B?ME1NYW5BQ1lHZ3IrRW1kS2pNOFdvZjY0YW5NQlJuT3EyR2xFYi9meHBtN2dV?= =?utf-8?B?aG1jUGNUaWNZT0dwVHRyY3RTU0s1SVp3UHdmZXlPdXdyTldCMzFRd29nYTRk?= =?utf-8?B?YzJkbnB4N2R2Vkt0RUFOOC8wM2k5b2tQMVk2OXNoemFENHY0anRYT1RwTzhm?= =?utf-8?B?d3hLdG5RYzd2Mmo0b05xUWlMMHc2dXJ3UWNjRi8yQ1VsVjNnNmJqcmxwNUsy?= =?utf-8?B?cW11T1B2bVhmZzNBc2I0UC9jdnVoUnQ4UGtNVStDV2Joa2Y5M3RkS1ZWK0FX?= =?utf-8?B?bURRN0lBQ0FwQlV6cmNiR2szdXRmVERsTXp6UnVOK29aTXVZblRRMUlqN2Zo?= =?utf-8?B?bkY1cTVuVndCT3hITzJJdXVDR0F5Z24vaDlkTXhkeHQzQUc2VEhMaDk2SCt5?= =?utf-8?B?UlgwNWd5ZWpWUXp3K0d2aHBFQ3BwZEFEWm5mdFQrZjc2YitxWEs2aWRYSzhC?= =?utf-8?B?WWJobWFvS2hsa05CWnZkd0puSHdrNCt1SEg3L3pYWEVWVzliNnIzUUVEcnd0?= =?utf-8?B?L0lyOEdoZm1Mb21VQ3VRdFR0a0dtRUVyK2lZYXFnaTFQd24yTVlHNWFoR0Nk?= =?utf-8?B?YzZndmJJTkJYUXMrWmNncm5CbXo3Z3FqTHRTMVBuemw2ZGh5Nmp1OW4vZWZI?= =?utf-8?B?ajQwalJQUkdubFd5YmpUNklwRVU2SWxTVzZjZkE4UFJSNzJGYXdpdDlxeGY0?= =?utf-8?B?dW9WTFNUQ1RoTkVPZnpEN283NkROY0ZubXhFQURqanlzMFk2YnpJRm1ZOHBw?= =?utf-8?B?cmtsb0pHV2JUKzBXVzRJUFJZdjJJM0tUOG9tYllMVzM3TlRxbkVKSlZqZFRY?= =?utf-8?B?dG5WRkN1OGROWVRMNUVRaUI3WERyVHRSVFN2OVlTZmlMeVdFUjRjVElzR3hJ?= =?utf-8?B?WFpqeEZtN3ltVHBWSno0elFvYXlhdGlJaldoelJmaXVNVE1ML3MrQzllVURx?= =?utf-8?B?TjVXSm1iREJ6N0dyS2VtVHFBakFiQktXTDArdFlrNzRseTlMWFZtUjJUNEJM?= =?utf-8?B?RU1QejBFNmZqd3RUMXpHb05VVFRVTUNvZVJEMytzRzlicC9xMGlueEFZYVJD?= =?utf-8?B?V25OL3dxUk9mekpoUTRlY0UwK2xvbUE3QzNFS2MzZ2x3WUJ5OENLTkNnQ0Vi?= =?utf-8?B?UmFEOC9aK3NrWVl2NUlNcTBNYnFQNkR5cHFheUNHeEFoREpGNCtvdFFGdFMx?= =?utf-8?B?ZHhFOGt2am9IU3lKU0xvUFNJcTF5d05xRmdHeHlWRHlLOWpFWHZyU2ZOVEhx?= =?utf-8?B?dVQxeG54bmpObmhRb1hmcGZIR21RN05LVXJFaURBMWdJQVR3NTh5WWJGcCtY?= =?utf-8?B?L1IxcDA0M0RscG40ODR0OUdJOWI4YUROaDE5eGlTTnFkd3k0dU9YbmNPeGE0?= =?utf-8?Q?ujRADfLN7Ia4gSNnb8eKCvKn01U4vr31iVsj0hA?= X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 9fd8817c-93f6-4279-0d92-08daa61ad575 X-MS-Exchange-CrossTenant-AuthSource: AS8P250MB0744.EURP250.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Oct 2022 15:12:20.8799 (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: AS8P250MB0282 Subject: Re: [FFmpeg-devel] [PATCH v6 2/3] libavcodec/flacenc: Implement encoding of 32 bit-per-sample PCM 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 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: Martijn van Beurden: > Add encoding of 32 bit-per-sample PCM to FLAC files to libavcodec. > Coding to this format is at this point considered experimental and > -strict experimental is needed to get ffmpeg to encode such files. > --- > libavcodec/flacenc.c | 518 ++++++++++++++++++++++++++++++++-------- > libavcodec/put_bits.h | 7 + > libavcodec/put_golomb.h | 14 -- > 3 files changed, 423 insertions(+), 116 deletions(-) > > diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c > index 5d8c3f82be..b69adaf4ba 100644 > --- a/libavcodec/flacenc.c > +++ b/libavcodec/flacenc.c > @@ -31,7 +31,6 @@ > #include "codec_internal.h" > #include "encode.h" > #include "put_bits.h" > -#include "put_golomb.h" > #include "lpc.h" > #include "flac.h" > #include "flacdata.h" > @@ -95,6 +94,7 @@ typedef struct FlacSubframe { > > typedef struct FlacFrame { > FlacSubframe subframes[FLAC_MAX_CHANNELS]; > + int64_t samples_33bps[FLAC_MAX_BLOCKSIZE]; > int blocksize; > int bs_code[2]; > uint8_t crc8; > @@ -282,10 +282,22 @@ static av_cold int flac_encode_init(AVCodecContext *avctx) > s->bps_code = 4; > break; > case AV_SAMPLE_FMT_S32: > - if (avctx->bits_per_raw_sample != 24) > - av_log(avctx, AV_LOG_WARNING, "encoding as 24 bits-per-sample\n"); > - avctx->bits_per_raw_sample = 24; > - s->bps_code = 6; > + if (avctx->bits_per_raw_sample <= 24) { > + if (avctx->bits_per_raw_sample < 24) > + av_log(avctx, AV_LOG_WARNING, "encoding as 24 bits-per-sample\n"); > + avctx->bits_per_raw_sample = 24; > + s->bps_code = 6; > + } else if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { > + av_log(avctx, AV_LOG_WARNING, > + "encoding as 24 bits-per-sample, more is considered " > + "experimental. Add -strict experimental if you want " > + "to encode more than 24 bits-per-sample\n"); > + avctx->bits_per_raw_sample = 24; > + s->bps_code = 6; > + } else { > + avctx->bits_per_raw_sample = 32; > + s->bps_code = 7; > + } > break; > } > > @@ -533,8 +545,7 @@ static uint64_t rice_count_exact(const int32_t *res, int n, int k) > uint64_t count = 0; > > for (i = 0; i < n; i++) { > - int32_t v = -2 * res[i] - 1; > - v ^= v >> 31; > + unsigned v = ((unsigned)(res[i]) << 1) ^ (res[i] >> 31); > count += (v >> k) + 1 + k; > } > return count; > @@ -713,8 +724,8 @@ static uint64_t calc_rice_params(RiceContext *rc, > > tmp_rc.coding_mode = rc->coding_mode; > > - for (i = 0; i < n; i++) > - udata[i] = (2 * data[i]) ^ (data[i] >> 31); > + for (i = pred_order; i < n; i++) > + udata[i] = ((unsigned)(data[i]) << 1) ^ (data[i] >> 31); > > calc_sum_top(pmax, exact ? kmax : 0, udata, n, pred_order, sums); > > @@ -812,6 +823,180 @@ static void encode_residual_fixed(int32_t *res, const int32_t *smp, int n, > } > > > +static int encode_residual_fixed_with_residual_limit(int32_t *res, const int32_t *smp, > + int n, int order) > +{ > + /* This function checks for every residual whether it can be > + * contained in + * function that called this function has to try something else */ > + int i; > + int64_t res64; > + > + for (i = 0; i < order; i++) > + res[i] = smp[i]; > + > + if (order == 0) { > + for (i = order; i < n; i++) { > + if (smp[i] == INT32_MIN) > + return 1; > + res[i] = smp[i]; > + } > + } else if (order == 1) { > + for (i = order; i < n; i++) { > + res64 = (int64_t)smp[i] - smp[i-1]; > + if (res64 <= INT32_MIN || res64 > INT32_MAX) > + return 1; > + res[i] = res64; > + } > + } else if (order == 2) { > + for (i = order; i < n; i++) { > + res64 = (int64_t)smp[i] - 2*(int64_t)smp[i-1] + smp[i-2]; > + if (res64 <= INT32_MIN || res64 > INT32_MAX) > + return 1; > + res[i] = res64; > + } > + } else if (order == 3) { > + for (i = order; i < n; i++) { > + res64 = (int64_t)smp[i] - 3*(int64_t)smp[i-1] + 3*(int64_t)smp[i-2] - smp[i-3]; > + if (res64 <= INT32_MIN || res64 > INT32_MAX) > + return 1; > + res[i] = res64; > + } > + } else { > + for (i = order; i < n; i++) { > + res64 = (int64_t)smp[i] - 4*(int64_t)smp[i-1] + 6*(int64_t)smp[i-2] - 4*(int64_t)smp[i-3] + smp[i-4]; > + if (res64 <= INT32_MIN || res64 > INT32_MAX) > + return 1; > + res[i] = res64; > + } > + } > + return 0; > +} > + > + > +static int encode_residual_fixed_with_residual_limit_33bps(int32_t *res, const int64_t *smp, > + int n, int order) > +{ > + /* This function checks for every residual whether it can be > + * contained in + * function that called this function has to try something else */ > + int i; > + int64_t res64; > + > + if (order == 0) { > + for (i = order; i < n; i++) { > + if (smp[i] <= INT32_MIN || smp[i] > INT32_MAX) > + return 1; > + res[i] = smp[i]; > + } > + } else if (order == 1) { > + for (i = order; i < n; i++) { > + res64 = smp[i] - smp[i-1]; > + if (res64 <= INT32_MIN || res64 > INT32_MAX) > + return 1; > + res[i] = res64; > + } > + } else if (order == 2) { > + for (i = order; i < n; i++) { > + res64 = smp[i] - 2*smp[i-1] + smp[i-2]; > + if (res64 <= INT32_MIN || res64 > INT32_MAX) > + return 1; > + res[i] = res64; > + } > + } else if (order == 3) { > + for (i = order; i < n; i++) { > + res64 = smp[i] - 3*smp[i-1] + 3*smp[i-2] - smp[i-3]; > + if (res64 <= INT32_MIN || res64 > INT32_MAX) > + return 1; > + res[i] = res64; > + } > + } else { > + for (i = order; i < n; i++) { > + res64 = smp[i] - 4*smp[i-1] + 6*smp[i-2] - 4*smp[i-3] + smp[i-4]; > + if (res64 <= INT32_MIN || res64 > INT32_MAX) > + return 1; > + res[i] = res64; > + } > + } > + return 0; > +} > + > + > +static int lpc_encode_with_residual_limit(int32_t *res, const int32_t *smp, int len, > + int order, int32_t *coefs, int shift) > +{ > + /* This function checks for every residual whether it can be > + * contained in + * function that called this function has to try something else */ > + for (int i = 0; i < order; i++) > + res[i] = smp[i]; > + for (int i = order; i < len; i++) { > + int64_t p = 0, tmp; > + for (int j = 0; j < order; j++) > + p += (int64_t)coefs[j]*smp[(i-1)-j]; > + p >>= shift; > + tmp = smp[i] - p; > + if (tmp <= INT32_MIN || tmp > INT32_MAX) > + return 1; > + res[i] = tmp; > + } > + return 0; > +} > + > +static int lpc_encode_with_residual_limit_33bps(int32_t *res, const int64_t *smp, int len, > + int order, int32_t *coefs, int shift) > +{ > + /* This function checks for every residual whether it can be > + * contained in + * function that called this function has to try something else */ > + for (int i = order; i < len; i++) { > + int64_t p = 0, tmp; > + for (int j = 0; j < order; j++) > + p += (int64_t)coefs[j]*smp[(i-1)-j]; > + p >>= shift; > + tmp = smp[i] - p; > + if (tmp <= INT32_MIN || tmp > INT32_MAX) > + return 1; > + res[i] = tmp; > + } > + return 0; > +} These two functions could be generated by a common macro. Same for encode_residual_fixed_with_residual_limit(). > + > +static int lpc_encode_choose_datapath(FlacEncodeContext *s, int32_t bps, > + int32_t *res, const int32_t *smp, > + const int64_t *smp_33bps, int len, > + int order, int32_t *coefs, int shift) > +{ > + uint64_t max_residual_value = 0; > + int64_t max_sample_value = ((int64_t)(1) << (bps-1)); > + /* This calculates the max size of any residual with the current > + * predictor, so we know whether we need to check the residual */ > + for (int i = 0; i < order; i++) > + max_residual_value += FFABS(max_sample_value * coefs[i]); > + max_residual_value >>= shift; > + max_residual_value += max_sample_value; > + if (bps > 32) { > + if (lpc_encode_with_residual_limit_33bps(res, smp_33bps, len, order, coefs, shift)) > + return 1; > + } else if (max_residual_value > INT32_MAX) { > + if (lpc_encode_with_residual_limit(res, smp, len, order, coefs, shift)) > + return 1; > + } else if (bps + s->options.lpc_coeff_precision + av_log2(order) <= 32) { > + s->flac_dsp.lpc16_encode(res, smp, len, order, coefs, shift); > + } else { > + s->flac_dsp.lpc32_encode(res, smp, len, order, coefs, shift); > + } > + return 0; > +} > + > +#define DEFAULT_TO_VERBATIM() \ > +{ \ > + sub->type = sub->type_code = FLAC_SUBFRAME_VERBATIM; \ > + if (sub->obits <= 32) \ > + memcpy(res, smp, n * sizeof(int32_t)); \ > + return subframe_count_exact(s, sub, 0); \ > +} > + > static int encode_residual_ch(FlacEncodeContext *s, int ch) > { > int i, n; > @@ -821,28 +1006,38 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) > int32_t coefs[MAX_LPC_ORDER][MAX_LPC_ORDER]; > int shift[MAX_LPC_ORDER]; > int32_t *res, *smp; > + int64_t *smp_33bps; > > - frame = &s->frame; > - sub = &frame->subframes[ch]; > - res = sub->residual; > - smp = sub->samples; > - n = frame->blocksize; > + frame = &s->frame; > + sub = &frame->subframes[ch]; > + res = sub->residual; > + smp = sub->samples; > + smp_33bps = frame->samples_33bps; > + n = frame->blocksize; > > /* CONSTANT */ > - for (i = 1; i < n; i++) > - if(smp[i] != smp[0]) > - break; > - if (i == n) { > - sub->type = sub->type_code = FLAC_SUBFRAME_CONSTANT; > - res[0] = smp[0]; > - return subframe_count_exact(s, sub, 0); > + if (sub->obits > 32) { > + for (i = 1; i < n; i++) > + if(smp_33bps[i] != smp_33bps[0]) > + break; > + if (i == n) { > + sub->type = sub->type_code = FLAC_SUBFRAME_CONSTANT; > + return subframe_count_exact(s, sub, 0); > + } > + } else { > + for (i = 1; i < n; i++) > + if(smp[i] != smp[0]) > + break; > + if (i == n) { > + sub->type = sub->type_code = FLAC_SUBFRAME_CONSTANT; > + res[0] = smp[0]; > + return subframe_count_exact(s, sub, 0); > + } > } > > /* VERBATIM */ > if (frame->verbatim_only || n < 5) { > - sub->type = sub->type_code = FLAC_SUBFRAME_VERBATIM; > - memcpy(res, smp, n * sizeof(int32_t)); > - return subframe_count_exact(s, sub, 0); > + DEFAULT_TO_VERBATIM(); > } > > min_order = s->options.min_prediction_order; > @@ -859,15 +1054,32 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) > opt_order = 0; > bits[0] = UINT32_MAX; > for (i = min_order; i <= max_order; i++) { > - encode_residual_fixed(res, smp, n, i); > + if (sub->obits == 33) { > + if (encode_residual_fixed_with_residual_limit_33bps(res, smp_33bps, n, i)) > + continue; > + } else if (sub->obits + i >= 32) { > + if (encode_residual_fixed_with_residual_limit(res, smp, n, i)) > + continue; > + } else > + encode_residual_fixed(res, smp, n, i); > bits[i] = find_subframe_rice_params(s, sub, i); > if (bits[i] < bits[opt_order]) > opt_order = i; > } > + if (opt_order == 0 && bits[0] == UINT32_MAX) { > + /* No predictor found with residuals within + * so encode a verbatim subframe instead */ > + DEFAULT_TO_VERBATIM(); > + } > sub->order = opt_order; > sub->type_code = sub->type | sub->order; > if (sub->order != max_order) { > - encode_residual_fixed(res, smp, n, sub->order); > + if (sub->obits == 33) > + encode_residual_fixed_with_residual_limit_33bps(res, smp_33bps, n, sub->order); > + else if (sub->obits + i >= 32) > + encode_residual_fixed_with_residual_limit(res, smp, n, sub->order); > + else > + encode_residual_fixed(res, smp, n, sub->order); > find_subframe_rice_params(s, sub, sub->order); > } > return subframe_count_exact(s, sub, sub->order); > @@ -875,6 +1087,14 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) > > /* LPC */ > sub->type = FLAC_SUBFRAME_LPC; > + if (sub->obits == 33) > + /* As ff_lpc_calc_coefs is shared with other codecs and the LSB > + * probably isn't predictable anyway, throw away LSB for analysis > + * so it fits 32 bit int and existing function can be used > + * unmodified */ > + for (i = 0; i < n; i++) > + smp[i] = smp_33bps[i] >> 1; > + > opt_order = ff_lpc_calc_coefs(&s->lpc_ctx, smp, n, min_order, max_order, > s->options.lpc_coeff_precision, coefs, shift, s->options.lpc_type, > s->options.lpc_passes, omethod, > @@ -895,13 +1115,8 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) > order = av_clip(order, min_order - 1, max_order - 1); > if (order == last_order) > continue; > - if (s->bps_code * 4 + s->options.lpc_coeff_precision + av_log2(order) <= 32) { > - s->flac_dsp.lpc16_encode(res, smp, n, order+1, coefs[order], > - shift[order]); > - } else { > - s->flac_dsp.lpc32_encode(res, smp, n, order+1, coefs[order], > - shift[order]); > - } > + if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, order+1, coefs[order], shift[order])) > + continue; > bits[i] = find_subframe_rice_params(s, sub, order+1); > if (bits[i] < bits[opt_index]) { > opt_index = i; > @@ -915,11 +1130,8 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) > opt_order = 0; > bits[0] = UINT32_MAX; > for (i = min_order-1; i < max_order; i++) { > - if (s->bps_code * 4 + s->options.lpc_coeff_precision + av_log2(i) <= 32) { > - s->flac_dsp.lpc16_encode(res, smp, n, i+1, coefs[i], shift[i]); > - } else { > - s->flac_dsp.lpc32_encode(res, smp, n, i+1, coefs[i], shift[i]); > - } > + if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, i+1, coefs[i], shift[i])) > + continue; > bits[i] = find_subframe_rice_params(s, sub, i+1); > if (bits[i] < bits[opt_order]) > opt_order = i; > @@ -937,11 +1149,8 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) > for (i = last-step; i <= last+step; i += step) { > if (i < min_order-1 || i >= max_order || bits[i] < UINT32_MAX) > continue; > - if (s->bps_code * 4 + s->options.lpc_coeff_precision + av_log2(i) <= 32) { > - s->flac_dsp.lpc32_encode(res, smp, n, i+1, coefs[i], shift[i]); > - } else { > - s->flac_dsp.lpc16_encode(res, smp, n, i+1, coefs[i], shift[i]); > - } > + if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, i+1, coefs[i], shift[i])) > + continue; > bits[i] = find_subframe_rice_params(s, sub, i+1); > if (bits[i] < bits[opt_order]) > opt_order = i; > @@ -978,11 +1187,8 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) > if (diffsum >8) > continue; > > - if (s->bps_code * 4 + s->options.lpc_coeff_precision + av_log2(opt_order - 1) <= 32) { > - s->flac_dsp.lpc16_encode(res, smp, n, opt_order, lpc_try, shift[opt_order-1]); > - } else { > - s->flac_dsp.lpc32_encode(res, smp, n, opt_order, lpc_try, shift[opt_order-1]); > - } > + if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, opt_order, lpc_try, shift[opt_order-1])) > + continue; > score = find_subframe_rice_params(s, sub, opt_order); > if (score < best_score) { > best_score = score; > @@ -999,10 +1205,10 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) > for (i = 0; i < sub->order; i++) > sub->coefs[i] = coefs[sub->order-1][i]; > > - if (s->bps_code * 4 + s->options.lpc_coeff_precision + av_log2(opt_order) <= 32) { > - s->flac_dsp.lpc16_encode(res, smp, n, sub->order, sub->coefs, sub->shift); > - } else { > - s->flac_dsp.lpc32_encode(res, smp, n, sub->order, sub->coefs, sub->shift); > + if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, sub->order, sub->coefs, sub->shift)) { > + /* No predictor found with residuals within + * so encode a verbatim subframe instead */ > + DEFAULT_TO_VERBATIM(); > } > > find_subframe_rice_params(s, sub, sub->order); > @@ -1069,54 +1275,88 @@ static int encode_frame(FlacEncodeContext *s) > > static void remove_wasted_bits(FlacEncodeContext *s) > { > - int ch, i; > + int ch, i, wasted_bits; > > for (ch = 0; ch < s->channels; ch++) { > FlacSubframe *sub = &s->frame.subframes[ch]; > - int32_t v = 0; > > - for (i = 0; i < s->frame.blocksize; i++) { > - v |= sub->samples[i]; > - if (v & 1) > - break; > - } > + if (sub->obits > 32) { > + int64_t v = 0; > + for (i = 0; i < s->frame.blocksize; i++) { > + v |= s->frame.samples_33bps[i]; > + if (v & 1) > + break; > + } > + > + if (!v || (v & 1)) > + return; > > - if (v && !(v & 1)) { > v = ff_ctz(v); > > + /* If any wasted bits are found, samples are moved > + * from frame.samples_33bps to frame.subframes[ch] */ > for (i = 0; i < s->frame.blocksize; i++) > - sub->samples[i] >>= v; > + sub->samples[i] = s->frame.samples_33bps[i] >> v; > + wasted_bits = v; > + } else { > + int32_t v = 0; > + for (i = 0; i < s->frame.blocksize; i++) { > + v |= sub->samples[i]; > + if (v & 1) > + break; > + } > + > + if (!v || (v & 1)) > + return; > > - sub->wasted = v; > - sub->obits -= v; > + v = ff_ctz(v); The return value of ff_ctz() is undefined if its argument is zero, i.e. if (int)v == 0. You are checking for !v above. Can it happen that (int)v is zero even if v is nonzero? > > - /* for 24-bit, check if removing wasted bits makes the range better > - suited for using RICE instead of RICE2 for entropy coding */ > - if (sub->obits <= 17) > - sub->rc.coding_mode = CODING_MODE_RICE; > + for (i = 0; i < s->frame.blocksize; i++) > + sub->samples[i] >>= v; > + wasted_bits = v; > } > + > + sub->wasted = wasted_bits; > + sub->obits -= wasted_bits; > + > + /* for 24-bit, check if removing wasted bits makes the range better > + * suited for using RICE instead of RICE2 for entropy coding */ > + if (sub->obits <= 17) > + sub->rc.coding_mode = CODING_MODE_RICE; > } > } > > > static int estimate_stereo_mode(const int32_t *left_ch, const int32_t *right_ch, int n, > - int max_rice_param) > + int max_rice_param, int bps) > { > int i, best; > - int32_t lt, rt; > uint64_t sum[4]; > uint64_t score[4]; > int k; > > /* calculate sum of 2nd order residual for each channel */ > sum[0] = sum[1] = sum[2] = sum[3] = 0; > - for (i = 2; i < n; i++) { > - lt = left_ch[i] - 2*left_ch[i-1] + left_ch[i-2]; > - rt = right_ch[i] - 2*right_ch[i-1] + right_ch[i-2]; > - sum[2] += FFABS((lt + rt) >> 1); > - sum[3] += FFABS(lt - rt); > - sum[0] += FFABS(lt); > - sum[1] += FFABS(rt); > + if(bps < 30) { > + int32_t lt, rt; > + for (i = 2; i < n; i++) { > + lt = left_ch[i] - 2*left_ch[i-1] + left_ch[i-2]; > + rt = right_ch[i] - 2*right_ch[i-1] + right_ch[i-2]; > + sum[2] += FFABS((lt + rt) >> 1); > + sum[3] += FFABS(lt - rt); > + sum[0] += FFABS(lt); > + sum[1] += FFABS(rt); > + } > + } else { > + int64_t lt, rt; These variables could be declared in the loop body. > + for (i = 2; i < n; i++) { We allow "for (int i = 2;". This goes for the whole patch. > + lt = (int64_t)left_ch[i] - 2*(int64_t)left_ch[i-1] + left_ch[i-2]; > + rt = (int64_t)right_ch[i] - 2*(int64_t)right_ch[i-1] + right_ch[i-2]; > + sum[2] += FFABS((lt + rt) >> 1); > + sum[3] += FFABS(lt - rt); > + sum[0] += FFABS(lt); > + sum[1] += FFABS(rt); > + } > } > /* estimate bit counts */ > for (i = 0; i < 4; i++) { > @@ -1147,12 +1387,14 @@ static void channel_decorrelation(FlacEncodeContext *s) > { > FlacFrame *frame; > int32_t *left, *right; > + int64_t *side_33bps; > int i, n; > > - frame = &s->frame; > - n = frame->blocksize; > - left = frame->subframes[0].samples; > - right = frame->subframes[1].samples; > + frame = &s->frame; > + n = frame->blocksize; > + left = frame->subframes[0].samples; > + right = frame->subframes[1].samples; > + side_33bps = frame->samples_33bps; > > if (s->channels != 2) { > frame->ch_mode = FLAC_CHMODE_INDEPENDENT; > @@ -1161,29 +1403,49 @@ static void channel_decorrelation(FlacEncodeContext *s) > > if (s->options.ch_mode < 0) { > int max_rice_param = (1 << frame->subframes[0].rc.coding_mode) - 2; > - frame->ch_mode = estimate_stereo_mode(left, right, n, max_rice_param); > + frame->ch_mode = estimate_stereo_mode(left, right, n, max_rice_param, s->avctx->bits_per_raw_sample); > } else > frame->ch_mode = s->options.ch_mode; > > /* perform decorrelation and adjust bits-per-sample */ > if (frame->ch_mode == FLAC_CHMODE_INDEPENDENT) > return; > - if (frame->ch_mode == FLAC_CHMODE_MID_SIDE) { > - int32_t tmp; > - for (i = 0; i < n; i++) { > - tmp = left[i]; > - left[i] = (tmp + right[i]) >> 1; > - right[i] = tmp - right[i]; > + if(s->avctx->bits_per_raw_sample == 32) { > + if (frame->ch_mode == FLAC_CHMODE_MID_SIDE) { > + int64_t tmp; > + for (i = 0; i < n; i++) { > + tmp = left[i]; > + left[i] = (tmp + right[i]) >> 1; > + side_33bps[i] = tmp - right[i]; > + } > + frame->subframes[1].obits++; > + } else if (frame->ch_mode == FLAC_CHMODE_LEFT_SIDE) { > + for (i = 0; i < n; i++) > + side_33bps[i] = (int64_t)left[i] - right[i]; > + frame->subframes[1].obits++; > + } else { > + for (i = 0; i < n; i++) > + side_33bps[i] = (int64_t)left[i] - right[i]; > + frame->subframes[0].obits++; > } > - frame->subframes[1].obits++; > - } else if (frame->ch_mode == FLAC_CHMODE_LEFT_SIDE) { > - for (i = 0; i < n; i++) > - right[i] = left[i] - right[i]; > - frame->subframes[1].obits++; > } else { > - for (i = 0; i < n; i++) > - left[i] -= right[i]; > - frame->subframes[0].obits++; > + if (frame->ch_mode == FLAC_CHMODE_MID_SIDE) { > + int32_t tmp; > + for (i = 0; i < n; i++) { > + tmp = left[i]; > + left[i] = (tmp + right[i]) >> 1; > + right[i] = tmp - right[i]; > + } > + frame->subframes[1].obits++; > + } else if (frame->ch_mode == FLAC_CHMODE_LEFT_SIDE) { > + for (i = 0; i < n; i++) > + right[i] = left[i] - right[i]; > + frame->subframes[1].obits++; > + } else { > + for (i = 0; i < n; i++) > + left[i] -= right[i]; > + frame->subframes[0].obits++; > + } > } > } > > @@ -1232,6 +1494,25 @@ static void write_frame_header(FlacEncodeContext *s) > } > > > +static inline void set_sr_golomb_flac(PutBitContext *pb, int i, int k) > +{ > + unsigned v, e; > + > + v = ((unsigned)(i) << 1) ^ (i >> 31); > + > + e = (v >> k) + 1; > + while (e > 31) { > + put_bits(pb, 31, 0); > + e -= 31; > + } > + put_bits(pb, e, 1); > + if (k) { > + unsigned mask = UINT32_MAX >> (32-k); > + put_bits(pb, k, v & mask); > + } > +} > + > + > static void write_subframes(FlacEncodeContext *s) > { > int ch; > @@ -1252,14 +1533,38 @@ static void write_subframes(FlacEncodeContext *s) > > /* subframe */ > if (sub->type == FLAC_SUBFRAME_CONSTANT) { > - put_sbits(&s->pb, sub->obits, res[0]); > + if(sub->obits == 33) > + put_sbits63(&s->pb, 33, s->frame.samples_33bps[0]); > + else if(sub->obits == 32) > + put_bits32(&s->pb, res[0]); > + else > + put_sbits(&s->pb, sub->obits, res[0]); > } else if (sub->type == FLAC_SUBFRAME_VERBATIM) { > - while (res < frame_end) > - put_sbits(&s->pb, sub->obits, *res++); > + if (sub->obits == 33) { > + int64_t *res64 = s->frame.samples_33bps; > + int64_t *frame_end64 = &s->frame.samples_33bps[s->frame.blocksize]; > + while (res64 < frame_end64) > + put_sbits63(&s->pb, 33, (*res64++)); > + } else if (sub->obits == 32) { > + while (res < frame_end) > + put_bits32(&s->pb, *res++); > + } else { > + while (res < frame_end) > + put_sbits(&s->pb, sub->obits, *res++); > + } > } else { > /* warm-up samples */ > - for (i = 0; i < sub->order; i++) > - put_sbits(&s->pb, sub->obits, *res++); > + if (sub->obits == 33) { > + for (i = 0; i < sub->order; i++) > + put_sbits63(&s->pb, 33, s->frame.samples_33bps[i]); > + res += sub->order; > + } else if (sub->obits == 32) { > + for (i = 0; i < sub->order; i++) > + put_bits32(&s->pb, *res++); > + } else { > + for (i = 0; i < sub->order; i++) > + put_sbits(&s->pb, sub->obits, *res++); > + } > > /* LPC coefficients */ > if (sub->type == FLAC_SUBFRAME_LPC) { > @@ -1284,7 +1589,7 @@ static void write_subframes(FlacEncodeContext *s) > int k = sub->rc.params[p]; > put_bits(&s->pb, sub->rc.coding_mode, k); > while (res < part_end) > - set_sr_golomb_flac(&s->pb, *res++, k, INT32_MAX, 0); > + set_sr_golomb_flac(&s->pb, *res++, k); > part_end = FFMIN(frame_end, part_end + psize); > } > } > @@ -1332,7 +1637,7 @@ static int update_md5_sum(FlacEncodeContext *s, const void *samples) > (const uint16_t *) samples, buf_size / 2); > buf = s->md5_buffer; > #endif > - } else { > + } else if (s->avctx->bits_per_raw_sample <= 24) { > int i; > const int32_t *samples0 = samples; > uint8_t *tmp = s->md5_buffer; > @@ -1342,6 +1647,15 @@ static int update_md5_sum(FlacEncodeContext *s, const void *samples) > AV_WL24(tmp + 3*i, v); > } > buf = s->md5_buffer; > + } else { > + /* s->avctx->bits_per_raw_sample <= 32 */ > + int i; > + const int32_t *samples0 = samples; > + uint8_t *tmp = s->md5_buffer; > + > + for (i = 0; i < s->frame.blocksize * s->channels; i++) > + AV_WL32(tmp + 4*i, samples0[i]); > + buf = s->md5_buffer; > } > av_md5_update(s->md5ctx, buf, buf_size); > > diff --git a/libavcodec/put_bits.h b/libavcodec/put_bits.h > index 4b4f977ad5..4561dc131a 100644 > --- a/libavcodec/put_bits.h > +++ b/libavcodec/put_bits.h > @@ -363,6 +363,13 @@ static inline void put_bits64(PutBitContext *s, int n, uint64_t value) > } > } > > +static inline void put_sbits63(PutBitContext *pb, int n, int64_t value) > +{ > + av_assert2(n >= 0 && n < 64); > + > + put_bits64(pb, n, (uint64_t)(value) & (~(UINT64_MAX << n))); > +} > + > /** > * Return the pointer to the byte where the bitstream writer will put > * the next bit. > diff --git a/libavcodec/put_golomb.h b/libavcodec/put_golomb.h > index 9ca911fc3c..df47fd2c0a 100644 > --- a/libavcodec/put_golomb.h > +++ b/libavcodec/put_golomb.h > @@ -151,18 +151,4 @@ static inline void set_sr_golomb(PutBitContext *pb, int i, int k, int limit, > set_ur_golomb(pb, v, k, limit, esc_len); > } > > -/** > - * write signed golomb rice code (flac). > - */ > -static inline void set_sr_golomb_flac(PutBitContext *pb, int i, int k, > - int limit, int esc_len) > -{ > - int v; > - > - v = -2 * i - 1; > - v ^= (v >> 31); > - > - set_ur_golomb_jpegls(pb, v, k, limit, esc_len); > -} > - > #endif /* AVCODEC_PUT_GOLOMB_H */ _______________________________________________ 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".