/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"@(#)mlib_c_VideoDCTQuantize.c	9.7	07/10/30 SMI"

/*
 * FUNCTIONS
 *	mlib_VideoDCT8x8Quantize_S16_U8[_NA]  - computes the forward DCT
 * 						in the intra mode and
 *						performs quantization
 *	mlib_VideoDCT8x8Quantize_S16_S16_B12[_NA] - computes forward DCT
 *						in the inter mode and
 *						 performs quantization
 *
 * SYNOPSIS
 *	mlib_status  mlib_VideoDCT8x8Quantize_S16_U8[_NA] (
 *					mlib_s16       coeffs[64],
 *					const mlib_u8 *block,
 *					const mlib_d64 qtable[64],
 *					mlib_s32       stride)
 *
 *	mlib_status  mlib_VideoDCT8x8Quantize_S16_S16_B12[_NA](
 *					mlib_s16        coeffs[64],
 *					const mlib_s16 *block,
 *					const mlib_d64  qtable[64])
 *
 *
 * ARGUMENTS
 *      coeffs	Pointer to output after DCT and quantization
 *		coefficients.
 *      block	Pointer to 8x8 block in current frame or
 *		motion-compensated reference block.
 *      qtable	Pointer to the quantization table generated by
 *		mlib_VideoQuantizeInit_S16.
 *      stride	Stride in bytes between adjacent rows in a block.
 *
 * RESTRICTIONS
 *	The block and the coeffs must be 8-byte aligned and the stride
 *	must be a multiple of 8 for mlib_VideoDCT8x8Quantize_S16_U8
 *	and mlib_VideoDCT8x8Quantize_S16_S16_B12.
 *
 *	The values of the block should be within [-2048, 2047] range
 *	for mlib_VideoDCT8x8Quantize_S16_S16_B12 and
 *	mlib_VideoDCT8x8Quantize_S16_S16_B12_NA.
 *
 * DESCRIPTION
 *	mlib_VideoDCT8x8Quantize_S16_U8[_NA] computes the forward
 *	discrete cosine transform (DCT) in the intra mode and
 *	performs quantization.
 *
 *	mlib_VideoDCT8x8Quantize_S16_S16_B12[_NA] computes the
 *	forward discrete cosine transform (DCT) in the inter mode
 *	and performs quantization.
 *
 *	DCT algorithm:
 *
 *	F(u,v) =
 *      1             7   7             pi*(2*x+1)*u      pi*(2*y+1)*v
 *	-*C(u)*C(v)* SUM SUM f(x,y)*cos(------------)*cos(------------)
 *      4            x=0 y=0                 16                16
 *
 *	C(u) = 1/sqrt(2) if u == 0, otherwise C(u) = 1
 *
 *	where	x = 0, 1, ... ,7; y = 0, 1, ... ,7
 *		u = 0, 1, ... ,7; v = 0, 1, ... ,7
 *
 *	Quantization algorithm:
 *
 *	if (F(u,v) > 0)
 *		coeffs(u,v) = (mlib_s32)(F(u,v) * qtable(u,v) + 0.5)
 *	else
 * 		coeffs(u,v) = (mlib_s32)(F(u,v) * qtable(u,v) - 0.5)
 *
 *	where	u = 0, 1, ... ,7; v = 0, 1, ... ,7
 */

#include <mlib_video.h>
/* *********************************************************** */

#if ! defined(__MEDIALIB_OLD_NAMES)
#if defined(__SUNPRO_C)

#pragma	weak mlib_VideoDCT8x8Quantize_S16_U8 = \
			__mlib_VideoDCT8x8Quantize_S16_U8
#pragma weak mlib_VideoDCT8x8Quantize_S16_U8_NA = \
			__mlib_VideoDCT8x8Quantize_S16_U8_NA
#pragma weak mlib_VideoDCT8x8Quantize_S16_S16_B12 = \
			__mlib_VideoDCT8x8Quantize_S16_S16_B12
#pragma weak mlib_VideoDCT8x8Quantize_S16_S16_B12_NA = \
			__mlib_VideoDCT8x8Quantize_S16_S16_B12_NA

#elif defined(__GNUC__)	/* defined(__SUNPRO_C) */
__typeof__(__mlib_VideoDCT8x8Quantize_S16_U8)	\
		mlib_VideoDCT8x8Quantize_S16_U8
__attribute__((weak, alias("__mlib_VideoDCT8x8Quantize_S16_U8")));
__typeof__(__mlib_VideoDCT8x8Quantize_S16_U8_NA) \
		mlib_VideoDCT8x8Quantize_S16_U8_NA
__attribute__((weak, alias("__mlib_VideoDCT8x8Quantize_S16_U8_NA")));
__typeof__(__mlib_VideoDCT8x8Quantize_S16_S16_B12) \
		mlib_VideoDCT8x8Quantize_S16_S16_B12
__attribute__((weak, alias("__mlib_VideoDCT8x8Quantize_S16_S16_B12")));
__typeof__(__mlib_VideoDCT8x8Quantize_S16_S16_B12_NA) \
		mlib_VideoDCT8x8Quantize_S16_S16_B12_NA
__attribute__((weak, alias("__mlib_VideoDCT8x8Quantize_S16_S16_B12_NA")));

#else /* defined(__SUNPRO_C) */

#error  "unknown platform"

#endif /* defined(__SUNPRO_C) */
#endif /* ! defined(__MEDIALIB_OLD_NAMES) */

/* *********************************************************** */

mlib_status
__mlib_VideoDCT8x8Quantize_S16_U8(
	mlib_s16 coeffs[64],
	const mlib_u8 *block,
	const mlib_d64 qtable[64],
	mlib_s32 stride)
{
	mlib_s32 i;
	mlib_s32 tmp;

	if (MLIB_FAILURE == __mlib_VideoDCT8x8_S16_U8(coeffs, block, stride))
		return (MLIB_FAILURE);

	for (i = 0; i < 64; i++) {
		tmp = coeffs[i];
		if (tmp > 0) {
			coeffs[i] = (mlib_s32)(tmp * qtable[i] + 0.5);
		} else {
			coeffs[i] = (mlib_s32)(tmp * qtable[i] - 0.5);
		}
	}
	return (MLIB_SUCCESS);
}

mlib_status
__mlib_VideoDCT8x8Quantize_S16_U8_NA(
	mlib_s16 coeffs[64],
	const mlib_u8 *block,
	const mlib_d64 qtable[64],
	mlib_s32 stride)
{
	if (block == NULL || coeffs == NULL || stride <= 0) {
		return (MLIB_FAILURE);
	}

	return (__mlib_VideoDCT8x8Quantize_S16_U8(coeffs, block,\
				qtable, stride));
}

mlib_status
__mlib_VideoDCT8x8Quantize_S16_S16_B12(
	mlib_s16 coeffs[64],
	const mlib_s16 *block,
	const mlib_d64 qtable[64])
{
	mlib_s32 i;
	mlib_s32 tmp;

	if (MLIB_FAILURE == __mlib_VideoDCT8x8_S16_S16_B12(coeffs, block))
		return (MLIB_FAILURE);

	for (i = 0; i < 64; i++) {
		tmp = coeffs[i];
		if (tmp > 0) {
			coeffs[i] = (mlib_s32)(tmp * qtable[i] + 0.5);
		} else {
			coeffs[i] = (mlib_s32)(tmp * qtable[i] - 0.5);
		}
	}

	return (MLIB_SUCCESS);
}

mlib_status
__mlib_VideoDCT8x8Quantize_S16_S16_B12_NA(
	mlib_s16 coeffs[64],
	const mlib_s16 *block,
	const mlib_d64 qtable[64])
{
	if (block == NULL || coeffs == NULL)
		return (MLIB_FAILURE);

	return (__mlib_VideoDCT8x8Quantize_S16_S16_B12(coeffs, block, qtable));

}
