Plan 9 from Bell Labs’s /usr/web/sources/contrib/cnielsen/bladeenc/reservoir.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
			(c) Copyright 1998-2000 - Tord Jansson
			======================================

		This file is part of the BladeEnc MP3 Encoder, based on
		ISO's reference code for MPEG Layer 3 compression, and might
		contain smaller or larger sections that are directly taken
		from ISO's reference code.

		All changes to the ISO reference code herein are either
		copyrighted by Tord Jansson (tord.jansson@swipnet.se)
		or sublicensed to Tord Jansson by a third party.

	BladeEnc is free software; you can redistribute this file
	and/or modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.



	------------    Changes    ------------

	2000-12-11  Andre Piotrowski

	-	reformatted
*/

#include	<stdio.h>
#include	<stdlib.h>
#include	<math.h>
#include	<assert.h>

#include	"common.h"
#include	"l3side.h"
#include	"loop.h"
#include	"huffman.h"
#include	"l3bitstream.h"
#include	"reservoir.h"





/*
	Layer3 bit reservoir:
	Described in C.1.5.4.2.2 of the IS
*/

static	int				ResvSize = 0;   /* in bits */
static	int				ResvMax  = 0;   /* in bits */





void					fixStatic_reservoir (void)
{
	ResvSize = 0;
	ResvMax  = 0;
}





/*
	ResvFrameBegin:
	Called at the beginning of a frame. Updates the maximum
	size of the reservoir, and checks to make sure main_data_begin
	was set properly by the formatter
*/
void					ResvFrameBegin
(
	frame_params			*fr_ps,
	III_side_info_t			*l3_side,
	int						mean_bits,
	int						frameLength
)
{
	layer					*info;
	int						fullFrameBits, mode_gr;
	int						expectedResvSize, resvLimit;


	info = fr_ps->header;
	mode_gr = 2;
	resvLimit = 4088; /* main_data_begin has 9 bits in MPEG 1 */


	/*
		main_data_begin was set by the formatter to the
		expected value for the next call -- this should
		agree with our reservoir size
	*/
	expectedResvSize = l3_side->main_data_begin * 8;
/*	assert (expectedResvSize == ResvSize); */

	fullFrameBits = mean_bits * mode_gr;

	/*
		determine maximum size of reservoir:
		ResvMax + frameLength <= 7680;

		limit max size to resvLimit bits because
		main_data_begin cannot indicate a
		larger value
	*/
	ResvMax = MIN(MAX (0, 7680-frameLength), resvLimit);
}





/*
	ResvMaxBits:
	Called at the beginning of each granule to get the max bit
	allowance for the current granule based on reservoir size
	and perceptual entropy.
*/
int						ResvMaxBits
(
	frame_params			*fr_ps,
	III_side_info_t			*l3_side,
	double					*pe,
	int						mean_bits
)
{
	int						more_bits, max_bits, add_bits, over_bits;


	mean_bits /= fr_ps->stereo;

	max_bits = mean_bits;

	if (ResvMax != 0)
	{
		more_bits = (int) (*pe * 3.1 - mean_bits);

		if (more_bits > 100)
		{
			int		frac = (ResvSize * 6) / 10;

			add_bits = MIN(frac, more_bits);
		}
		else
			add_bits = 0;

		over_bits = ResvSize - ((ResvMax * 8) / 10) - add_bits;
 		if (over_bits > 0)
			add_bits += over_bits;

		max_bits += add_bits;
	}

	if (max_bits > 4095)
		max_bits = 4095;

	return max_bits;
}





/*
	ResvAdjust:
	Called after a granule's bit allocation. Readjusts the size of
	the reservoir to reflect the granule's usage.
*/
void					ResvAdjust
(
	frame_params			*fr_ps,
	gr_info					*cod_info,
	III_side_info_t			*l3_side,
	int						mean_bits
)
{
	ResvSize += (mean_bits / fr_ps->stereo) - cod_info->part2_3_length;
}





/*
	ResvFrameEnd:
	Called after all granules in a frame have been allocated. Makes sure
	that the reservoir size is within limits, possibly by adding stuffing
	bits. Note that stuffing bits are added by increasing a granule's
	part2_3_length. The bitstream formatter will detect this and write the
	appropriate stuffing bits to the bitstream.
*/
void					ResvFrameEnd
(
	frame_params			*fr_ps,
	III_side_info_t			*l3_side,
	int						mean_bits
)
{
	layer					*info;
	gr_info					*cod_info;
	int						mode_gr, gr, ch, stereo, ancillary_pad, stuffingBits;
	int						over_bits;

	info    = fr_ps->header;
	stereo  = fr_ps->stereo;
	mode_gr = 2;

	ancillary_pad = 0;

	/* just in case mean_bits is odd, this is necessary... */
	if ((stereo == 2)  &&  (mean_bits & 1))
		ResvSize ++;

	stuffingBits = ancillary_pad;
	
	if ((over_bits = ResvSize - ResvMax) > 0)
	{
		stuffingBits += over_bits;
		ResvSize     -= over_bits;
	}

	/* we must be byte aligned */
	if ((over_bits = ResvSize % 8) != 0)
	{
		stuffingBits += over_bits;
		ResvSize     -= over_bits;
	}

	if (stuffingBits)
	{
		/*
			plan a: put all into the first granule
			This was preferred by someone designing a
			real-time decoder...
		*/
		cod_info = &l3_side->gr[0].ch[0].tt;

		if (cod_info->part2_3_length + stuffingBits < 4095)
			cod_info->part2_3_length += stuffingBits;
		else
		{
		    /* plan b: distribute throughout the granules */
		    for (gr = 0;  gr < mode_gr;  gr++)
		    {
				for (ch = 0;  ch < stereo;  ch++)
				{
					int			extraBits, bitsThisGr;
					gr_info		*cod_info = &l3_side->gr[gr].ch[ch].tt;

					if (stuffingBits == 0)
						break;
					extraBits = 4095 - cod_info->part2_3_length;
					bitsThisGr = (extraBits < stuffingBits) ? extraBits : stuffingBits;
					cod_info->part2_3_length += bitsThisGr;
					stuffingBits -= bitsThisGr;
				}
			}
		    /*
				If any stuffing bits remain, we elect to spill them
				into ancillary data. The bitstream formatter will do this if
				l3side->resvDrain is set
		    */
		    l3_side->resvDrain = stuffingBits;
		}
	}
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.