LCOV - code coverage report
Current view: top level - lib_enc - ivas_range_uni_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 124 127 97.6 %
Date: 2025-05-03 01:55:50 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <assert.h>
      34             : #include "ivas_prot_fx.h"
      35             : #include "ivas_cnst.h"
      36             : #include "ivas_stat_enc.h"
      37             : #include "cnst.h"
      38             : #include "rom_com.h"
      39             : #include <stdint.h>
      40             : #include "options.h"
      41             : #include "prot_fx.h"
      42             : #include "wmc_auto.h"
      43             : 
      44             : 
      45             : /*
      46             :  * After finalizing the range encoder, the produced bits are available in the
      47             :  * rc_st_enc->byte_buffer member array. The bits are packed into bytes, MSB first, as
      48             :  * byte_buffer[0].bit[7], ..., byte_buffer[0].bit[0], byte_buffer[1].bit[7], ...
      49             :  * The last byte may contain less than 8 bits. The total bit count is returned
      50             :  * by the rc_uni_enc_finish function but can also be computed afterwards as
      51             :  * total_bit_count = (rc_st_enc->byte_count - 1) * 8 + rc_st_enc->last_byte_bit_count
      52             :  */
      53             : 
      54             : /*-------------------------------------------------------------------*
      55             :  * Local function prototypes
      56             :  *-------------------------------------------------------------------*/
      57             : 
      58             : static void rc_uni_enc_shift_fx( RangeUniEncState *rc_st_enc );
      59             : 
      60             : 
      61             : /*-------------------------------------------------------------------*
      62             :  * rc_uni_enc_init_fx()
      63             :  *
      64             :  * Initalize the range encoder
      65             :  *-------------------------------------------------------------------*/
      66      901194 : void rc_uni_enc_init_fx(
      67             :     RangeUniEncState *rc_st_enc /* i/o: RC state handle         */
      68             : )
      69             : {
      70      901194 :     rc_st_enc->rc_low = 0;
      71      901194 :     rc_st_enc->rc_range = 0xFFFFFFFF;
      72      901194 :     rc_st_enc->rc_cache = -1;
      73      901194 :     rc_st_enc->rc_carry = 0;
      74      901194 :     rc_st_enc->rc_carry_count = 0;
      75             : 
      76      901194 :     rc_st_enc->byte_count = 0;
      77      901194 :     rc_st_enc->last_byte_bit_count = -1;
      78      901194 :     move32();
      79      901194 :     move32();
      80      901194 :     move16();
      81      901194 :     move16();
      82      901194 :     move16();
      83      901194 :     move16();
      84      901194 :     move16();
      85             : 
      86      901194 :     return;
      87             : }
      88             : 
      89             : /*-------------------------------------------------------------------*
      90             :  * rc_uni_enc_encode_fast()
      91             :  *
      92             :  * Encode given cumulative frequency and frequency when total frequency is a power of 2
      93             :  *-------------------------------------------------------------------*/
      94   216077650 : void rc_uni_enc_encode_fast_fx(
      95             :     RangeUniEncState *rc_st_enc, /* i/o: RC state handle                     */
      96             :     const UWord16 cum_freq,      /* i  : Cumulative frequency up to symbol   */
      97             :     const UWord16 sym_freq,      /* i  : Symbol frequency                    */
      98             :     const UWord16 tot_shift      /* i  : Total frequency as a power of 2     */
      99             : )
     100             : {
     101             :     UWord32 r, tmp;
     102             : 
     103   216077650 :     r = UL_lshr( rc_st_enc->rc_range, tot_shift );
     104   216077650 :     tmp = UL_Mpy_32_32( r, (UWord32) cum_freq );
     105             : 
     106   216077650 :     rc_st_enc->rc_low = UL_addNsD( rc_st_enc->rc_low, tmp );
     107   216077650 :     move32();
     108   216077650 :     if ( LT_64( rc_st_enc->rc_low, tmp ) )
     109             :     {
     110    11353446 :         rc_st_enc->rc_carry = 1;
     111    11353446 :         move16();
     112             :     }
     113             : 
     114   216077650 :     rc_st_enc->rc_range = UL_Mpy_32_32( r, (UWord32) sym_freq );
     115   216077650 :     move32();
     116             : 
     117             :     /* rc_range was shifted right by up to 16, so at most two renormalizations are needed */
     118   216077650 :     IF( LT_64( rc_st_enc->rc_range, 0x01000000 ) )
     119             :     {
     120    65044470 :         rc_st_enc->rc_range = UL_lshl( rc_st_enc->rc_range, 8 );
     121    65044470 :         move32();
     122    65044470 :         rc_uni_enc_shift_fx( rc_st_enc );
     123    65044470 :         IF( LT_64( rc_st_enc->rc_range, 0x01000000 ) )
     124             :         {
     125       72720 :             rc_st_enc->rc_range = UL_lshl( rc_st_enc->rc_range, 8 );
     126       72720 :             move32();
     127       72720 :             rc_uni_enc_shift_fx( rc_st_enc );
     128             :         }
     129             :     }
     130             : 
     131   216077650 :     return;
     132             : }
     133             : 
     134             : 
     135             : /*-------------------------------------------------------------------*
     136             :  * rc_uni_enc_encode_symbol_fastS_fx()
     137             :  *
     138             :  * Encode an alphabet symbol when total frequency is a power of 2
     139             :  *-------------------------------------------------------------------*/
     140   215370336 : void rc_uni_enc_encode_symbol_fastS_fx(
     141             :     RangeUniEncState *rc_st_enc, /* i/o: Encoder state                       */
     142             :     const UWord16 symbol,        /* i  : Symbol to encode                    */
     143             :     const UWord16 cum_freq[],    /* i  : Cumulative frequency up to symbol   */
     144             :     const UWord16 sym_freq[],    /* i  : Symbol frequency                    */
     145             :     const UWord16 tot_shift      /* i  : Total frequency as a power of 2     */
     146             : )
     147             : {
     148   215370336 :     rc_uni_enc_encode_fast_fx( rc_st_enc, cum_freq[symbol], sym_freq[symbol], tot_shift );
     149             : 
     150   215370336 :     return;
     151             : }
     152             : 
     153             : /*-------------------------------------------------------------------*
     154             :  * rc_uni_enc_finish_fx()
     155             :  *
     156             :  * Finalize the range encoder
     157             :  *-------------------------------------------------------------------*/
     158             : /*! r: Total number of bits produced */
     159      890483 : Word16 rc_uni_enc_finish_fx(
     160             :     RangeUniEncState *rc_st_enc /* i/o: RC state handle               */
     161             : )
     162             : {
     163             :     Word16 total_bit_count;
     164             :     UWord32 val, mask;
     165             :     Word16 bits;
     166             : 
     167             :     /* floor(log2(x)) = floor(log2(x >> 24)) + 24, for any x >= 2 ^ 24 */
     168             :     /* 32 - floor(log2(y)) = norm_ul_float(y) + 1 = norm_l(y >> 24) - 22 */
     169      890483 :     bits = sub( norm_l( UL_lshr( rc_st_enc->rc_range, 24 ) ), 22 ); /* bits = 32 - floor(log2(rc_range)) */
     170             :     /* completely equivalent with norm_ul_float(rc_st_enc->rc_range) + 1, but norm_l is faster */
     171             : 
     172      890483 :     bits = add( bits, 1 ); /* conservative number of bits, because the decoder only has rc_range available */
     173             : 
     174             : 
     175      890483 :     mask = UL_lshr( 0xFFFFFFFFu, bits );
     176      890483 :     val = UL_and( UL_addNsD( rc_st_enc->rc_low, mask ), ~mask );
     177             : 
     178      890483 :     if ( LT_64( val, rc_st_enc->rc_low ) )
     179             :     {
     180       54742 :         rc_st_enc->rc_carry = 1;
     181       54742 :         move16();
     182             :     }
     183             : 
     184      890483 :     rc_st_enc->rc_low = val;
     185      890483 :     move32();
     186             : 
     187     1892176 :     WHILE( bits > 0 )
     188             :     {
     189     1001693 :         rc_uni_enc_shift_fx( rc_st_enc );
     190     1001693 :         bits = sub( bits, 8 );
     191             :     }
     192             : 
     193      890483 :     bits = add( bits, 8 );
     194             : 
     195      890483 :     IF( rc_st_enc->rc_carry_count > 0 )
     196             :     {
     197             :         /* rc_carry_count > 0, therefore the last call to rc_uni_enc_shift incremented rc_carry_count */
     198         420 :         IF( rc_st_enc->rc_cache >= 0 ) /* may actually be always true, but it is difficult to prove formally */
     199             :         {
     200         420 :             rc_st_enc->byte_buffer[rc_st_enc->byte_count] = (UWord8) add( rc_st_enc->rc_cache, rc_st_enc->rc_carry );
     201         420 :             rc_st_enc->byte_count = add( rc_st_enc->byte_count, 1 );
     202         420 :             move16();
     203         420 :             move16();
     204             :         }
     205             : 
     206         421 :         WHILE( GT_16( rc_st_enc->rc_carry_count, 1 ) )
     207             :         {
     208           1 :             rc_st_enc->byte_buffer[rc_st_enc->byte_count] = (UWord8) add( rc_st_enc->rc_carry, 0xFF );
     209           1 :             rc_st_enc->byte_count = add( rc_st_enc->byte_count, 1 );
     210           1 :             rc_st_enc->rc_carry_count = sub( rc_st_enc->rc_carry_count, 1 );
     211           1 :             move16();
     212           1 :             move16();
     213           1 :             move16();
     214             :         }
     215             :         /* pack the last 1 to 8 bits into the MSB of the last byte, with zero padding into the LSB */
     216         420 :         rc_st_enc->byte_buffer[rc_st_enc->byte_count] = (UWord8) L_and( L_deposit_l( add( rc_st_enc->rc_carry, 0xFF ) ), L_shl( 0xFFu, sub( 8, bits ) ) );
     217         420 :         rc_st_enc->byte_count = add( rc_st_enc->byte_count, 1 );
     218         420 :         rc_st_enc->last_byte_bit_count = bits;
     219         420 :         move16();
     220         420 :         move16();
     221         420 :         move16();
     222             :     }
     223             :     ELSE
     224             :     {
     225             :         /* rc_carry_count == 0, therefore the last call to rc_uni_enc_shift wrote into rc_cache */
     226             :         /* pack the last 1 to 8 bits into the MSB of the last byte, with zero padding into the LSB */
     227      890063 :         rc_st_enc->byte_buffer[rc_st_enc->byte_count] = (UWord8) L_and( L_deposit_l( add( rc_st_enc->rc_carry, rc_st_enc->rc_cache ) ), L_shl( 0xFFu, sub( 8, bits ) ) );
     228      890063 :         rc_st_enc->byte_count = add( rc_st_enc->byte_count, 1 );
     229      890063 :         rc_st_enc->last_byte_bit_count = bits;
     230      890063 :         move16();
     231      890063 :         move16();
     232      890063 :         move16();
     233             :     }
     234             : 
     235             : 
     236      890483 :     total_bit_count = add( shl( sub( rc_st_enc->byte_count, 1 ), 3 ), rc_st_enc->last_byte_bit_count );
     237             : 
     238      890483 :     return total_bit_count;
     239             : }
     240             : 
     241             : 
     242             : /*-------------------------------------------------------------------*
     243             :  * rc_uni_enc_virtual_finish()
     244             :  *
     245             :  * Get the total number of bits that would be produced by finalization
     246             :  *-------------------------------------------------------------------*/
     247             : /*! r: Total number of bits produced */
     248     1182531 : Word16 rc_uni_enc_virtual_finish_fx(
     249             :     RangeUniEncState *rc_st_enc /* i  : RC state handle               */
     250             : )
     251             : {
     252             : 
     253             :     /*
     254             :       byte_count bytes have already been written to the byte_buffer array
     255             :       1 byte is pending if rc_cache >= 0, consisting of rc_cache or rc_cache + 1
     256             :         the pending byte bits are computed as 8 - 8 * ((uint16_t) rc_st_enc->rc_cache >> 15)
     257             :       rc_carry_count bytes are pending, consisting of 0x00 or 0xFF
     258             :       bits bits will be additionally written during the finalization procedure
     259             :         bits is computed as norm_l(rc_st_enc->rc_range >> 24) - 21, as in rc_uni_enc_finish
     260             :     */
     261             : 
     262             :     Word16 tmp;
     263     1182531 :     IF( rc_st_enc->rc_cache > 0 )
     264             :     {
     265     1085767 :         tmp = sub( norm_l( UL_lshr( rc_st_enc->rc_range, 24 ) ), 13 );
     266             :     }
     267             :     ELSE
     268             :     {
     269       96764 :         tmp = sub( norm_l( UL_lshr( rc_st_enc->rc_range, 24 ) ), 13 + 8 );
     270             :     }
     271     1182531 :     tmp = add( tmp, shl( add( rc_st_enc->byte_count, rc_st_enc->rc_carry_count ), 3 ) );
     272             : 
     273             :     // return ( ( rc_st_enc->byte_count + rc_st_enc->rc_carry_count ) << 3 ) +
     274             :     //        norm_l( rc_st_enc->rc_range >> 24 ) - 13 - 8 * ( (uint16_t) rc_st_enc->rc_cache >> 15 );
     275             : 
     276     1182531 :     return tmp;
     277             : }
     278             : 
     279             : 
     280             : /*-------------------------------------------------------------------*
     281             :  * rc_uni_enc_shift_fx()
     282             :  *
     283             :  * Shift a byte out to bitstream (internal function)
     284             :  *-------------------------------------------------------------------*/
     285    66185512 : static void rc_uni_enc_shift_fx(
     286             :     RangeUniEncState *rc_st_enc /* i/o: RC state handle     */
     287             : )
     288             : {
     289    66185512 :     test();
     290    66185512 :     IF( LT_64( rc_st_enc->rc_low, 0xFF000000u ) || rc_st_enc->rc_carry )
     291             :     {
     292    65925286 :         IF( rc_st_enc->rc_cache >= 0 )
     293             :         {
     294    65024974 :             rc_st_enc->byte_buffer[rc_st_enc->byte_count] = (UWord8) add( rc_st_enc->rc_cache, rc_st_enc->rc_carry );
     295    65024974 :             rc_st_enc->byte_count = add( rc_st_enc->byte_count, 1 );
     296    65024974 :             move16();
     297    65024974 :             move16();
     298             :         }
     299             : 
     300    66185053 :         WHILE( rc_st_enc->rc_carry_count > 0 )
     301             :         {
     302      259767 :             rc_st_enc->byte_buffer[rc_st_enc->byte_count] = (UWord8) add( rc_st_enc->rc_carry, 0xFF );
     303      259767 :             rc_st_enc->byte_count = add( rc_st_enc->byte_count, 1 );
     304      259767 :             rc_st_enc->rc_carry_count = sub( rc_st_enc->rc_carry_count, 1 );
     305      259767 :             move16();
     306      259767 :             move16();
     307      259767 :             move16();
     308             :         }
     309             : 
     310    65925286 :         rc_st_enc->rc_cache = extract_l( UL_lshr( rc_st_enc->rc_low, 24 ) );
     311    65925286 :         rc_st_enc->rc_carry = 0;
     312    65925286 :         move16();
     313    65925286 :         move16();
     314             :     }
     315             :     ELSE
     316             :     {
     317      260226 :         rc_st_enc->rc_carry_count = add( rc_st_enc->rc_carry_count, 1 );
     318      260226 :         move16();
     319             :     }
     320             : 
     321    66185512 :     rc_st_enc->rc_low = UL_lshl( rc_st_enc->rc_low, 8 );
     322    66185512 :     move32();
     323             : 
     324    66185512 :     return;
     325             : }
     326             : 
     327             : 
     328             : /*-------------------------------------------------------------------*
     329             :  * rc_uni_enc_encode_bits_fx()
     330             :  *
     331             :  * Encode up to 16 bits with uniform probability
     332             :  *-------------------------------------------------------------------*/
     333      526743 : void rc_uni_enc_encode_bits_fx(
     334             :     RangeUniEncState *rc_st_enc, /* i/o: RC state handle     */
     335             :     const UWord16 value,         /* i  : Value to encode     */
     336             :     const Word16 bits            /* i  : Number of bits      */
     337             : )
     338             : {
     339             :     UWord32 tmp;
     340             : 
     341      526743 :     rc_st_enc->rc_range = UL_lshr( rc_st_enc->rc_range, bits );
     342      526743 :     move32();
     343      526743 :     tmp = UL_Mpy_32_32( rc_st_enc->rc_range, value );
     344             : 
     345      526743 :     rc_st_enc->rc_low = UL_addNsD( rc_st_enc->rc_low, tmp );
     346      526743 :     move32();
     347      526743 :     if ( LT_64( rc_st_enc->rc_low, tmp ) )
     348             :     {
     349       23652 :         rc_st_enc->rc_carry = 1;
     350       23652 :         move16();
     351             :     }
     352             : 
     353             :     /* rc_range was shifted right by up to 16, so at most two renormalizations are needed */
     354      526743 :     IF( LT_64( rc_st_enc->rc_range, 0x01000000 ) )
     355             :     {
     356       66629 :         rc_st_enc->rc_range = UL_lshl( rc_st_enc->rc_range, 8 );
     357       66629 :         move32();
     358       66629 :         rc_uni_enc_shift_fx( rc_st_enc );
     359       66629 :         IF( LT_64( rc_st_enc->rc_range, 0x01000000 ) )
     360             :         {
     361           0 :             rc_st_enc->rc_range = UL_lshl( rc_st_enc->rc_range, 8 );
     362           0 :             move32();
     363           0 :             rc_uni_enc_shift_fx( rc_st_enc );
     364             :         }
     365             :     }
     366             : 
     367      526743 :     return;
     368             : }

Generated by: LCOV version 1.14