blob: c80552a5fe2fefe0a80aa65452e938390c786701 [file] [log] [blame]
/*
* Copyright (C) 2007-2008 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
*
* File Name: omxVCM4P10_GetVLCInfo.c
* OpenMAX DL: v1.0.2
* Revision: 9641
* Date: Thursday, February 7, 2008
*
*
*
* Description:
*
* This function extracts run-length encoding (RLE) information
*/
#include "omxtypes.h"
#include "armOMX.h"
#include "omxVC.h"
#include "armCOMM.h"
#include "armVC.h"
/**
* Function: omxVCM4P10_GetVLCInfo (6.3.5.9.1)
*
* Description:
* This function extracts run-length encoding (RLE) information from the
* coefficient matrix. The results are returned in an OMXVCM4P10VLCInfo
* structure.
*
* Input Arguments:
*
* pSrcCoeff - pointer to the transform coefficient matrix. 8-byte
* alignment required.
* pScanMatrix - pointer to the scan order definition matrix. For a luma
* block the scan matrix should follow [ISO14496-10] section 8.5.4,
* and should contain the values 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13,
* 10, 7, 11, 14, 15. For a chroma block, the scan matrix should
* contain the values 0, 1, 2, 3.
* bAC - indicates presence of a DC coefficient; 0 = DC coefficient
* present, 1= DC coefficient absent.
* MaxNumCoef - specifies the number of coefficients contained in the
* transform coefficient matrix, pSrcCoeff. The value should be 16
* for blocks of type LUMADC, LUMAAC, LUMALEVEL, and CHROMAAC. The
* value should be 4 for blocks of type CHROMADC.
*
* Output Arguments:
*
* pDstVLCInfo - pointer to structure that stores information for
* run-length coding.
*
* Return Value:
*
* OMX_Sts_NoErr - no error
* OMX_Sts_BadArgErr - bad arguments; returned if any of the following
* conditions are true:
* - at least one of the following pointers is NULL:
* pSrcCoeff, pScanMatrix, pDstVLCInfo
* - pSrcCoeff is not aligned on an 8-byte boundary
*
*/
OMXResult omxVCM4P10_GetVLCInfo (
const OMX_S16* pSrcCoeff,
const OMX_U8* pScanMatrix,
OMX_U8 bAC,
OMX_U32 MaxNumCoef,
OMXVCM4P10VLCInfo* pDstVLCInfo
)
{
OMX_INT i, MinIndex;
OMX_S32 Value;
OMX_U32 Mask = 4, RunBefore;
OMX_S16 *pLevel;
OMX_U8 *pRun;
OMX_S16 Buf [16];
/* check for argument error */
armRetArgErrIf(pSrcCoeff == NULL, OMX_Sts_BadArgErr)
armRetArgErrIf(armNot8ByteAligned(pSrcCoeff), OMX_Sts_BadArgErr)
armRetArgErrIf(pScanMatrix == NULL, OMX_Sts_BadArgErr)
armRetArgErrIf(pDstVLCInfo == NULL, OMX_Sts_BadArgErr)
armRetArgErrIf(bAC > 1, OMX_Sts_BadArgErr)
armRetArgErrIf(MaxNumCoef > 16, OMX_Sts_BadArgErr)
/* Initialize RLE Info structure */
pDstVLCInfo->uTrailing_Ones = 0;
pDstVLCInfo->uTrailing_One_Signs = 0;
pDstVLCInfo->uNumCoeffs = 0;
pDstVLCInfo->uTotalZeros = 0;
for (i = 0; i < 16; i++)
{
pDstVLCInfo->iLevels [i] = 0;
pDstVLCInfo->uRuns [i] = 0;
}
MinIndex = (bAC == 0 && MaxNumCoef == 15) ? 1 : 0;
for (i = MinIndex; i < (MaxNumCoef + MinIndex); i++)
{
/* Scan */
Buf [i - MinIndex] = pSrcCoeff [pScanMatrix [i]];
}
/* skip zeros at the end */
i = MaxNumCoef - 1;
while (!Buf [i] && i >= 0)
{
i--;
}
if (i < 0)
{
return OMX_Sts_NoErr;
}
/* Fill RLE Info structure */
pLevel = pDstVLCInfo->iLevels;
pRun = pDstVLCInfo->uRuns;
RunBefore = 0;
/* Handle first non zero separate */
pDstVLCInfo->uNumCoeffs++;
Value = Buf [i];
if (Value == 1 || Value == -1)
{
pDstVLCInfo->uTrailing_Ones++;
pDstVLCInfo->uTrailing_One_Signs |=
Value == -1 ? Mask : 0;
Mask >>= 1;
}
else
{
Value -= (Value > 0 ? 1 : -1);
*pLevel++ = Value;
Mask = 0;
}
/* Remaining non zero */
while (--i >= 0)
{
Value = Buf [i];
if (Value)
{
pDstVLCInfo->uNumCoeffs++;
/* Mask becomes zero after entering */
if (Mask &&
(Value == 1 ||
Value == -1))
{
pDstVLCInfo->uTrailing_Ones++;
pDstVLCInfo->uTrailing_One_Signs |=
Value == -1 ? Mask : 0;
Mask >>= 1;
*pRun++ = RunBefore;
RunBefore = 0;
}
else
{
/* If 3 trailing ones are not completed */
if (Mask)
{
Mask = 0;
Value -= (Value > 0 ? 1 : -1);
}
*pLevel++ = Value;
*pRun++ = RunBefore;
RunBefore = 0;
}
}
else
{
pDstVLCInfo->uTotalZeros++;
RunBefore++;
}
}
/* Update last run */
if (RunBefore)
{
*pRun++ = RunBefore;
}
return OMX_Sts_NoErr;
}
/*****************************************************************************
* END OF FILE
*****************************************************************************/