You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
346 lines
9.6 KiB
346 lines
9.6 KiB
/*
|
|
* Copyright (C) 2009 The Android Open Source Project
|
|
* Modified for use by h264bsd standalone library
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Table of contents
|
|
|
|
1. Include headers
|
|
2. External compiler flags
|
|
3. Module defines
|
|
4. Local function prototypes
|
|
5. Functions
|
|
h264bsdWriteMacroblock
|
|
h264bsdWriteOutputBlocks
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
/*------------------------------------------------------------------------------
|
|
1. Include headers
|
|
------------------------------------------------------------------------------*/
|
|
|
|
#include "h264bsd_image.h"
|
|
#include "h264bsd_util.h"
|
|
#include "h264bsd_neighbour.h"
|
|
|
|
/*------------------------------------------------------------------------------
|
|
2. External compiler flags
|
|
--------------------------------------------------------------------------------
|
|
|
|
--------------------------------------------------------------------------------
|
|
3. Module defines
|
|
------------------------------------------------------------------------------*/
|
|
|
|
/* x- and y-coordinates for each block, defined in h264bsd_intra_prediction.c */
|
|
extern const u32 h264bsdBlockX[];
|
|
extern const u32 h264bsdBlockY[];
|
|
|
|
/* clipping table, defined in h264bsd_intra_prediction.c */
|
|
extern const u8 h264bsdClip[];
|
|
|
|
/*------------------------------------------------------------------------------
|
|
4. Local function prototypes
|
|
------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Function: h264bsdWriteMacroblock
|
|
|
|
Functional description:
|
|
Write one macroblock into the image. Both luma and chroma
|
|
components will be written at the same time.
|
|
|
|
Inputs:
|
|
data pointer to macroblock data to be written, 256 values for
|
|
luma followed by 64 values for both chroma components
|
|
|
|
Outputs:
|
|
image pointer to the image where the macroblock will be written
|
|
|
|
Returns:
|
|
none
|
|
|
|
------------------------------------------------------------------------------*/
|
|
#ifndef H264DEC_NEON
|
|
void h264bsdWriteMacroblock(image_t *image, u8 *data)
|
|
{
|
|
|
|
/* Variables */
|
|
|
|
u32 i;
|
|
u32 width;
|
|
u32 *lum, *cb, *cr;
|
|
u32 *ptr;
|
|
u32 tmp1, tmp2;
|
|
|
|
/* Code */
|
|
|
|
ASSERT(image);
|
|
ASSERT(data);
|
|
ASSERT(!((u32)data&0x3));
|
|
|
|
width = image->width;
|
|
|
|
/*lint -save -e826 lum, cb and cr used to copy 4 bytes at the time, disable
|
|
* "area too small" info message */
|
|
lum = (u32*)image->luma;
|
|
cb = (u32*)image->cb;
|
|
cr = (u32*)image->cr;
|
|
ASSERT(!((u32)lum&0x3));
|
|
ASSERT(!((u32)cb&0x3));
|
|
ASSERT(!((u32)cr&0x3));
|
|
|
|
ptr = (u32*)data;
|
|
|
|
width *= 4;
|
|
for (i = 16; i ; i--)
|
|
{
|
|
tmp1 = *ptr++;
|
|
tmp2 = *ptr++;
|
|
*lum++ = tmp1;
|
|
*lum++ = tmp2;
|
|
tmp1 = *ptr++;
|
|
tmp2 = *ptr++;
|
|
*lum++ = tmp1;
|
|
*lum++ = tmp2;
|
|
lum += width-4;
|
|
}
|
|
|
|
width >>= 1;
|
|
for (i = 8; i ; i--)
|
|
{
|
|
tmp1 = *ptr++;
|
|
tmp2 = *ptr++;
|
|
*cb++ = tmp1;
|
|
*cb++ = tmp2;
|
|
cb += width-2;
|
|
}
|
|
|
|
for (i = 8; i ; i--)
|
|
{
|
|
tmp1 = *ptr++;
|
|
tmp2 = *ptr++;
|
|
*cr++ = tmp1;
|
|
*cr++ = tmp2;
|
|
cr += width-2;
|
|
}
|
|
|
|
}
|
|
#endif
|
|
#ifndef H264DEC_OMXDL
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Function: h264bsdWriteOutputBlocks
|
|
|
|
Functional description:
|
|
Write one macroblock into the image. Prediction for the macroblock
|
|
and the residual are given separately and will be combined while
|
|
writing the data to the image
|
|
|
|
Inputs:
|
|
data pointer to macroblock prediction data, 256 values for
|
|
luma followed by 64 values for both chroma components
|
|
mbNum number of the macroblock
|
|
residual pointer to residual data, 16 16-element arrays for luma
|
|
followed by 4 16-element arrays for both chroma
|
|
components
|
|
|
|
Outputs:
|
|
image pointer to the image where the data will be written
|
|
|
|
Returns:
|
|
none
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
void h264bsdWriteOutputBlocks(image_t *image, u32 mbNum, u8 *data,
|
|
i32 residual[][16])
|
|
{
|
|
|
|
/* Variables */
|
|
|
|
u32 i;
|
|
u32 picWidth, picSize;
|
|
u8 *lum, *cb, *cr;
|
|
u8 *imageBlock;
|
|
u8 *tmp;
|
|
u32 row, col;
|
|
u32 block;
|
|
u32 x, y;
|
|
i32 *pRes;
|
|
i32 tmp1, tmp2, tmp3, tmp4;
|
|
const u8 *clp = h264bsdClip + 512;
|
|
|
|
/* Code */
|
|
|
|
ASSERT(image);
|
|
ASSERT(data);
|
|
ASSERT(mbNum < image->width * image->height);
|
|
ASSERT(!((u32)data&0x3));
|
|
|
|
/* Image size in macroblocks */
|
|
picWidth = image->width;
|
|
picSize = picWidth * image->height;
|
|
row = mbNum / picWidth;
|
|
col = mbNum % picWidth;
|
|
|
|
/* Output macroblock position in output picture */
|
|
lum = (image->data + row * picWidth * 256 + col * 16);
|
|
cb = (image->data + picSize * 256 + row * picWidth * 64 + col * 8);
|
|
cr = (cb + picSize * 64);
|
|
|
|
picWidth *= 16;
|
|
|
|
for (block = 0; block < 16; block++)
|
|
{
|
|
x = h264bsdBlockX[block];
|
|
y = h264bsdBlockY[block];
|
|
|
|
pRes = residual[block];
|
|
|
|
ASSERT(pRes);
|
|
|
|
tmp = data + y*16 + x;
|
|
imageBlock = lum + y*picWidth + x;
|
|
|
|
ASSERT(!((u32)tmp&0x3));
|
|
ASSERT(!((u32)imageBlock&0x3));
|
|
|
|
if (IS_RESIDUAL_EMPTY(pRes))
|
|
{
|
|
/*lint -e826 */
|
|
i32 *in32 = (i32*)tmp;
|
|
i32 *out32 = (i32*)imageBlock;
|
|
|
|
/* Residual is zero => copy prediction block to output */
|
|
tmp1 = *in32; in32 += 4;
|
|
tmp2 = *in32; in32 += 4;
|
|
*out32 = tmp1; out32 += picWidth/4;
|
|
*out32 = tmp2; out32 += picWidth/4;
|
|
tmp1 = *in32; in32 += 4;
|
|
tmp2 = *in32;
|
|
*out32 = tmp1; out32 += picWidth/4;
|
|
*out32 = tmp2;
|
|
}
|
|
else
|
|
{
|
|
|
|
RANGE_CHECK_ARRAY(pRes, -512, 511, 16);
|
|
|
|
/* Calculate image = prediction + residual
|
|
* Process four pixels in a loop */
|
|
for (i = 4; i; i--)
|
|
{
|
|
tmp1 = tmp[0];
|
|
tmp2 = *pRes++;
|
|
tmp3 = tmp[1];
|
|
tmp1 = clp[tmp1 + tmp2];
|
|
tmp4 = *pRes++;
|
|
imageBlock[0] = (u8)tmp1;
|
|
tmp3 = clp[tmp3 + tmp4];
|
|
tmp1 = tmp[2];
|
|
tmp2 = *pRes++;
|
|
imageBlock[1] = (u8)tmp3;
|
|
tmp1 = clp[tmp1 + tmp2];
|
|
tmp3 = tmp[3];
|
|
tmp4 = *pRes++;
|
|
imageBlock[2] = (u8)tmp1;
|
|
tmp3 = clp[tmp3 + tmp4];
|
|
tmp += 16;
|
|
imageBlock[3] = (u8)tmp3;
|
|
imageBlock += picWidth;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
picWidth /= 2;
|
|
|
|
for (block = 16; block <= 23; block++)
|
|
{
|
|
x = h264bsdBlockX[block & 0x3];
|
|
y = h264bsdBlockY[block & 0x3];
|
|
|
|
pRes = residual[block];
|
|
|
|
ASSERT(pRes);
|
|
|
|
tmp = data + 256;
|
|
imageBlock = cb;
|
|
|
|
if (block >= 20)
|
|
{
|
|
imageBlock = cr;
|
|
tmp += 64;
|
|
}
|
|
|
|
tmp += y*8 + x;
|
|
imageBlock += y*picWidth + x;
|
|
|
|
ASSERT(!((u32)tmp&0x3));
|
|
ASSERT(!((u32)imageBlock&0x3));
|
|
|
|
if (IS_RESIDUAL_EMPTY(pRes))
|
|
{
|
|
/*lint -e826 */
|
|
i32 *in32 = (i32*)tmp;
|
|
i32 *out32 = (i32*)imageBlock;
|
|
|
|
/* Residual is zero => copy prediction block to output */
|
|
tmp1 = *in32; in32 += 2;
|
|
tmp2 = *in32; in32 += 2;
|
|
*out32 = tmp1; out32 += picWidth/4;
|
|
*out32 = tmp2; out32 += picWidth/4;
|
|
tmp1 = *in32; in32 += 2;
|
|
tmp2 = *in32;
|
|
*out32 = tmp1; out32 += picWidth/4;
|
|
*out32 = tmp2;
|
|
}
|
|
else
|
|
{
|
|
|
|
RANGE_CHECK_ARRAY(pRes, -512, 511, 16);
|
|
|
|
for (i = 4; i; i--)
|
|
{
|
|
tmp1 = tmp[0];
|
|
tmp2 = *pRes++;
|
|
tmp3 = tmp[1];
|
|
tmp1 = clp[tmp1 + tmp2];
|
|
tmp4 = *pRes++;
|
|
imageBlock[0] = (u8)tmp1;
|
|
tmp3 = clp[tmp3 + tmp4];
|
|
tmp1 = tmp[2];
|
|
tmp2 = *pRes++;
|
|
imageBlock[1] = (u8)tmp3;
|
|
tmp1 = clp[tmp1 + tmp2];
|
|
tmp3 = tmp[3];
|
|
tmp4 = *pRes++;
|
|
imageBlock[2] = (u8)tmp1;
|
|
tmp3 = clp[tmp3 + tmp4];
|
|
tmp += 8;
|
|
imageBlock[3] = (u8)tmp3;
|
|
imageBlock += picWidth;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif /* H264DEC_OMXDL */
|
|
|
|
|